authorgravatar for antonin.decimo@gmail.comAntonin Décimo <antonin.decimo@gmail.com> 2026-03-17 01:35:27+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-18 00:45:50+01:00
log83add375c4734a6091dfc31563482b1b7157c1d6
tree9c6b7c2307dd1688e3ded39d458158c33e004ff3
parentc38e6ed6862c4abfb6c3ab6c8cdd1ea13961969b

zld: fix null dereference parsing Mach-O non-existing atom or FDE

If the unwind record address has not been added to `superposition` (maybe it is not in the current symbol table mapping?) then there's a panic on null dereference. Ensure the entry exists in `superposition`.

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

src/link/MachO/Object.zig+14-2
...@@ -1295,7 +1295,13 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target....@@ -1295,7 +1295,13 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
1295 const rec = self.getUnwindRecord(rec_index);1295 const rec = self.getUnwindRecord(rec_index);
1296 const atom = rec.getAtom(macho_file);1296 const atom = rec.getAtom(macho_file);
1297 const addr = atom.getInputAddress(macho_file) + rec.atom_offset;1297 const addr = atom.getInputAddress(macho_file) + rec.atom_offset;
1298 superposition.getPtr(addr).?.cu = rec_index;1298
1299 try superposition.ensureUnusedCapacity(1);
1300 const gop = superposition.getOrPutAssumeCapacity(addr);
1301 if (!gop.found_existing) {
1302 gop.value_ptr.* = .{ .atom = rec.atom, .size = rec.length };
1303 }
1304 gop.value_ptr.cu = rec_index;
1299 }1305 }
13001306
1301 const FdeRange = struct { start: u64, end: u64 };1307 const FdeRange = struct { start: u64, end: u64 };
...@@ -1305,7 +1311,13 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target....@@ -1305,7 +1311,13 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
1305 for (self.fdes.items, 0..) |fde, fde_index| {1311 for (self.fdes.items, 0..) |fde, fde_index| {
1306 const atom = fde.getAtom(macho_file);1312 const atom = fde.getAtom(macho_file);
1307 const addr = atom.getInputAddress(macho_file) + fde.atom_offset;1313 const addr = atom.getInputAddress(macho_file) + fde.atom_offset;
1308 superposition.getPtr(addr).?.fde = @intCast(fde_index);1314
1315 try superposition.ensureUnusedCapacity(1);
1316 const gop = superposition.getOrPutAssumeCapacity(addr);
1317 if (!gop.found_existing) {
1318 gop.value_ptr.* = .{ .atom = fde.atom, .size = fde.pc_range };
1319 }
1320 gop.value_ptr.fde = @intCast(fde_index);
13091321
1310 // Build FDE range for coverage check1322 // Build FDE range for coverage check
1311 const pc_range = fde.pc_range;1323 const pc_range = fde.pc_range;