authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-10 19:08:44-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
loge18a397c85797caf6ff3ac58a57b236a45277f17
tree3692a8b27e98004bb7f52a6c1a24f623b29e8016
parent9c14645b58dffa9fb1578170440f32b63f924a85

wasm linker: fix corruption of string bytes

if any fixups are emitted in lowering data, keep the string bytes allocated even if all zeroes because it is used as a fixup staging area.

1 files changed, 16 insertions(+), 8 deletions(-)

src/link/Wasm.zig+16-8
...@@ -3064,7 +3064,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -3064,7 +3064,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
30643064
3065 dev.check(.wasm_backend);3065 dev.check(.wasm_backend);
30663066
3067 const gpa = pt.zcu.gpa;3067 const zcu = pt.zcu;
3068 const gpa = zcu.gpa;
3068 try wasm.functions.ensureUnusedCapacity(gpa, 1);3069 try wasm.functions.ensureUnusedCapacity(gpa, 1);
3069 try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);3070 try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);
30703071
...@@ -3074,9 +3075,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -3074,9 +3075,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
3074 // That lowering happens during `flush`, after garbage collection, which3075 // That lowering happens during `flush`, after garbage collection, which
3075 // can affect function and global indexes, which affects the LEB integer3076 // can affect function and global indexes, which affects the LEB integer
3076 // encoding, which affects the output binary size.3077 // encoding, which affects the output binary size.
3077 wasm.zcu_funcs.putAssumeCapacity(func_index, .{3078 const function = try CodeGen.function(wasm, pt, func_index, air, liveness);
3078 .function = try CodeGen.function(wasm, pt, func_index, air, liveness),3079 wasm.zcu_funcs.putAssumeCapacity(func_index, .{ .function = function });
3079 });
3080 wasm.functions.putAssumeCapacity(.pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.entries.len - 1) }), {});3080 wasm.functions.putAssumeCapacity(.pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.entries.len - 1) }), {});
30813081
3082 try zds.finish(wasm, pt);3082 try zds.finish(wasm, pt);
...@@ -3356,7 +3356,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v...@@ -3356,7 +3356,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v
3356 }3356 }
3357}3357}
33583358
3359fn markFunctionImport(3359pub fn markFunctionImport(
3360 wasm: *Wasm,3360 wasm: *Wasm,
3361 name: String,3361 name: String,
3362 import: *FunctionImport,3362 import: *FunctionImport,
...@@ -4455,12 +4455,19 @@ pub fn isBss(wasm: *const Wasm, optional_name: OptionalString) bool {...@@ -4455,12 +4455,19 @@ pub fn isBss(wasm: *const Wasm, optional_name: OptionalString) bool {
4455fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj {4455fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj {
4456 const code_start: u32 = @intCast(wasm.string_bytes.items.len);4456 const code_start: u32 = @intCast(wasm.string_bytes.items.len);
4457 const relocs_start: u32 = @intCast(wasm.out_relocs.len);4457 const relocs_start: u32 = @intCast(wasm.out_relocs.len);
4458 const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len);
4459 const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len);
4460 const func_table_fixups_start: u32 = @intCast(wasm.func_table_fixups.items.len);
4458 wasm.string_bytes_lock.lock();4461 wasm.string_bytes_lock.lock();
44594462
4460 try codegen.generateSymbol(&wasm.base, pt, .unneeded, .fromInterned(ip_index), &wasm.string_bytes, .none);4463 try codegen.generateSymbol(&wasm.base, pt, .unneeded, .fromInterned(ip_index), &wasm.string_bytes, .none);
44614464
4462 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);4465 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);
4463 const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start);4466 const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start);
4467 const any_fixups =
4468 uav_fixups_start != wasm.uav_fixups.items.len or
4469 nav_fixups_start != wasm.nav_fixups.items.len or
4470 func_table_fixups_start != wasm.func_table_fixups.items.len;
4464 wasm.string_bytes_lock.unlock();4471 wasm.string_bytes_lock.unlock();
44654472
4466 const naive_code: DataPayload = .{4473 const naive_code: DataPayload = .{
...@@ -4469,8 +4476,9 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu...@@ -4469,8 +4476,9 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu
4469 };4476 };
44704477
4471 // Only nonzero init values need to take up space in the output.4478 // Only nonzero init values need to take up space in the output.
4472 const all_zeroes = std.mem.allEqual(u8, naive_code.slice(wasm), 0);4479 // If any fixups are present, we still need the string bytes allocated since
4473 const code: DataPayload = if (!all_zeroes) naive_code else c: {4480 // that is the staging area for the fixups.
4481 const code: DataPayload = if (!any_fixups and std.mem.allEqual(u8, naive_code.slice(wasm), 0)) c: {
4474 wasm.string_bytes.shrinkRetainingCapacity(code_start);4482 wasm.string_bytes.shrinkRetainingCapacity(code_start);
4475 // Indicate empty by making off and len the same value, however, still4483 // Indicate empty by making off and len the same value, however, still
4476 // transmit the data size by using the size as that value.4484 // transmit the data size by using the size as that value.
...@@ -4478,7 +4486,7 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu...@@ -4478,7 +4486,7 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu
4478 .off = .none,4486 .off = .none,
4479 .len = naive_code.len,4487 .len = naive_code.len,
4480 };4488 };
4481 };4489 } else naive_code;
44824490
4483 return .{4491 return .{
4484 .code = code,4492 .code = code,