commit 62d4204f21332d97ad7697f628eade9137e9c3bc
parent de9d0c8926b01712f924bccd731415f96a1bffce
Author: Sebastian <sebastian@sebsite.pw>
Date: Thu, 23 Jun 2022 19:19:43 -0400
gen: fix segfault when allocating multiple of 2^32
In QBE, the jnz instruction only checks the lower 32 bits of its first
argument (i.e. it's treated as a word). Since the passed size was being
checked directly, any multiple of 2^32 would be treated as zero,
resulting in a segfault at runtime.
let n: size = 64 * 64 * 1024 * 1024;
let x: []u8 = alloc([0...], n);
This has been fixed by first using cnel to compare the size to zero, and
then using the result of that in the jnz instruction.
Fixes: https://todo.sr.ht/~sircmpwn/hare/739
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/gen.c b/src/gen.c
@@ -430,9 +430,11 @@ gen_alloc_slice_at(struct gen_context *ctx,
struct qbe_value rtfunc = mkrtfunc(ctx, "rt.malloc");
struct qbe_value data = mkqtmp(ctx, ctx->arch.ptr, ".%d");
+ struct qbe_value cmpres = mkqtmp(ctx, &qbe_word, ".%d");
struct qbe_value zero = constl(0);
pushi(ctx->current, &data, Q_COPY, &zero, NULL);
- pushi(ctx->current, NULL, Q_JNZ, &size, &bnonzero, &bzero, NULL);
+ pushi(ctx->current, &cmpres, Q_CNEL, &size, &zero, NULL);
+ pushi(ctx->current, NULL, Q_JNZ, &cmpres, &bnonzero, &bzero, NULL);
push(&ctx->current->body, &lnonzero);
pushi(ctx->current, &data, Q_CALL, &rtfunc, &size, NULL);