Protect against different vector widths (#1909)

GCC aligns alloca to the widest enabled vector type (16 bytes, 32 with avx,
64 with avx-512). With AVX the block address is `lea 0x1f(%rsp)` rounded down
to the nearest 32-divisible, but half the time the block starts 16 bytes higher
so the function reads the stack arguments 2 slots away from where it should.
Without AVX the address is `lea 0xf(%rsp)` which is the stack pointer.
This commit is contained in:
Alex Alejandre
2026-10-07 21:55:15 -05:00
committed by GitHub
parent 3bc551a29d
commit 78f5996fcf
+8
View File
@@ -1225,7 +1225,15 @@ static Janet janet_ffi_sysv64(JanetFFISignature *signature, void *function_point
ret_mem = alloca(type_size(signature->ret.type));
regs[0] = (uint64_t) ret_mem;
}
/* GCC aligns alloca to the widest allowed vector type (32 bytes for AVX) which can pad
* between the stack pointer and this block, but stack args start at the stack pointer,
* so we must ask for the calling convention's 16 byte alignment */
/* Both GCC and CLANG define GNUC. */
#if defined(__GNUC__)
uint64_t *stack = __builtin_alloca_with_align(sizeof(uint64_t) * signature->stack_count, 128);
#else
uint64_t *stack = alloca(sizeof(uint64_t) * signature->stack_count);
#endif
for (uint32_t i = 0; i < signature->arg_count; i++) {
uint64_t *to;
int32_t n = i + 2;