commit 81fd59f11f174708cdac9150fa3ff50e462f2e4b
parent 2853a1eb9a2dda5d3afcbcc2202d797bc17d291f
Author: Michael Forney <mforney@mforney.org>
Date: Wed, 22 Sep 2021 12:33:34 -0700
gen: fix out-of-bounds write in cast to narrower union for match
If we have something like
export fn f() (void | i32) = {
let x: (void | i32 | i64) = 1234i32;
return match (x) {
y: (void | i32) => y,
* => abort(),
};
};
the types in the inner union of the `to` type are a subset of the
types in the inner union of the `from` type. However, harec was
generating a copy of the full `from` union, which results in writing
past the end of the storage allocated for the `to` union, as well
as unaligned stores.
To fix this, use the narrower union type for the generated copy.
Fixes tests/18-match on riscv64.
Diffstat:
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/gen.c b/src/gen.c
@@ -1090,8 +1090,9 @@ gen_expr_cast_tagged_at(struct gen_context *ctx,
return;
}
+ subtype = tagged_subset_compat(to, from) ? from : to;
const struct type *innertype = type_store_tagged_to_union(
- ctx->store, type_dealias(from));
+ ctx->store, type_dealias(subtype));
struct gen_value iout = mktemp(ctx, innertype, ".%d");
struct gen_value ival = mktemp(ctx, innertype, ".%d");
struct qbe_value qiout = mkqval(ctx, &iout);