harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit ba423ce6f0a2692e2105645b05b2beb09c061c28
parent e3e640acce7abd063b8c698e704852344472b99c
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 11 Aug 2021 09:34:11 +0200

gen: fix use-after-free on append to self

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mrt/ensure.ha | 3+++
Msrc/gen.c | 10+++++++---
Mtests/configure | 2+-
3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/rt/ensure.ha b/rt/ensure.ha @@ -6,6 +6,9 @@ export type slice = struct { export fn ensure(s: *slice, membsz: size) void = { let cap = s.capacity; + if (cap >= s.length) { + return; + }; for (cap < s.length) { assert(cap >= s.capacity, "slice out of memory (overflow)"); if (cap == 0) { diff --git a/src/gen.c b/src/gen.c @@ -532,8 +532,8 @@ gen_expr_append(struct gen_context *ctx, const struct expression *expr) vlen = constl(vtype->array.length); break; case STORAGE_SLICE: - vlen = mkqtmp(ctx, ctx->arch.sz, ".%d"); - pushi(ctx->current, &vdata, load, &qvobj, NULL); + vlen = mkqtmp(ctx, ctx->arch.sz, "vlen.%d"); + pushi(ctx->current, &vdata, Q_COPY, &qvobj, NULL); pushi(ctx->current, &ptr, Q_ADD, &qvobj, &offs, NULL); pushi(ctx->current, &vlen, load, &ptr, NULL); break; @@ -572,6 +572,7 @@ gen_expr_append(struct gen_context *ctx, const struct expression *expr) } offs = mkqtmp(ctx, ctx->arch.sz, ".%d"); + ptr = mkqtmp(ctx, ctx->arch.ptr, ".%d"); pushi(ctx->current, &ptr, load, &qslice, NULL); pushi(ctx->current, &offs, Q_MUL, &len, &membsz, NULL); pushi(ctx->current, &ptr, Q_ADD, &ptr, &offs, NULL); @@ -588,9 +589,12 @@ gen_expr_append(struct gen_context *ctx, const struct expression *expr) } if (expr->append.variadic) { - struct qbe_value rtfunc = mkrtfunc(ctx, "rt.memcpy"); + struct qbe_value rtfunc = mkrtfunc(ctx, "rt.memmove"); struct qbe_value sz = mkqtmp(ctx, ctx->arch.sz, ".%d"); pushi(ctx->current, &sz, Q_MUL, &vlen, &membsz, NULL); + if (vtype->storage == STORAGE_SLICE) { + pushi(ctx->current, &vdata, load, &vdata, NULL); + } pushi(ctx->current, NULL, Q_CALL, &rtfunc, &ptr, &vdata, &sz, NULL); } diff --git a/tests/configure b/tests/configure @@ -57,6 +57,7 @@ EOF 15-enums \ 16-defer \ 17-alloc \ + 19-append \ 20-if \ 24-imports \ 25-promotion \ @@ -66,7 +67,6 @@ EOF # Disabled tests #18-match \ - #19-append \ #21-tuples \ #22-delete \ #23-errors \