harec

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

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:
Msrc/gen.c | 3++-
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);