authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-07 12:58:19+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-17 18:08:58+01:00
loge8ef01f2221a8588ab86863fdb109b47fd6ceb50
treed8c5e45778d03c77d558a0231fabda9ac5e000e7
parent65c3a07709156a721090635ae6e6a16d7ccb95da
signaturelock-open Commit is signed but in an unrecognized format.

Elf2: fix expected_nodes_len calculation

I'm not sure what the basis was for the old logic here, but it was incorrect and caused an assertion failure in some cases. The dependencies on `maybe_interp` and `any_non_single_threaded` are already correctly modeled by `phnum`, so do not need to be accounted for a second time.

1 files changed, 4 insertions(+), 4 deletions(-)

src/link/Elf2.zig+4-4
...@@ -1123,13 +1123,13 @@ fn initHeaders(...@@ -1123,13 +1123,13 @@ fn initHeaders(
1123 const expected_nodes_len = expected_nodes_len: switch (@"type") {1123 const expected_nodes_len = expected_nodes_len: switch (@"type") {
1124 .NONE, .CORE, _ => unreachable,1124 .NONE, .CORE, _ => unreachable,
1125 .REL => {1125 .REL => {
1126 // Each phdr is actually going to be an shdr.
1126 defer phnum = 0;1127 defer phnum = 0;
1127 break :expected_nodes_len 5 + phnum;1128 break :expected_nodes_len 5 + phnum;
1128 },1129 },
1129 .EXEC, .DYN => break :expected_nodes_len 8 + phnum * 2 +1130 .EXEC, .DYN => break :expected_nodes_len 10 +
1130 @intFromBool(maybe_interp != null) +1131 phnum * 2 - 1 + // each phdr also has a matching shdr, except for the PT_PHDR phdr
1131 @as(usize, 4) * @intFromBool(have_dynamic_section) +1132 @as(usize, 4) * @intFromBool(have_dynamic_section), // .dynstr, .dynsym, .rela.dyn, .rela.plt
1132 @intFromBool(comp.config.any_non_single_threaded),
1133 };1133 };
1134 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);1134 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
1135 try elf.shdrs.ensureTotalCapacity(gpa, shnum);1135 try elf.shdrs.ensureTotalCapacity(gpa, shnum);