authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-05-19 20:14:34+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-05-19 20:22:48+02:00
log832330094c00391ecd6f0ea4abf2d05261b5a10c
treee4405f62cb2b698c00504f08059cf7f89cf5291d
parentca870aa00504accd49e7f1d2fceed1e4b8d21100
signaturelock-open Commit is signed but in an unrecognized format.

wasm: aggregate_init - ensure zeroed result local

When initializing a packed struct, we must ensure the result local is zero'd. Previously we would do this by ensuring a new local is allocated. Although a local is always zero by default, it meant that if such an initialization was being done inside a loop, it would re- use that very same local that could potentially still hold a different value. Because this value is `or`'d with the value, it would result in a miscompilation. By manually setting this result to 0, we guarantee the correct behavior.

1 files changed, 9 insertions(+), 2 deletions(-)

src/arch/wasm/CodeGen.zig+9-2
......@@ -4893,8 +4893,15 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48934893 const struct_obj = result_ty.castTag(.@"struct").?.data;
48944894 const fields = struct_obj.fields.values();
48954895 const backing_type = struct_obj.backing_int_ty;
4896 // we ensure a new local is created so it's zero-initialized
4897 const result = try func.ensureAllocLocal(backing_type);
4896
4897 // ensure the result is zero'd
4898 const result = try func.allocLocal(backing_type);
4899 if (struct_obj.backing_int_ty.bitSize(func.target) <= 32)
4900 try func.addImm32(0)
4901 else
4902 try func.addImm64(0);
4903 try func.addLabel(.local_set, result.local.value);
4904
48984905 var current_bit: u16 = 0;
48994906 for (elements, 0..) |elem, elem_index| {
49004907 const field = fields[elem_index];