authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-15 09:04:07+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-16 10:37:20+01:00
log29bcd2d54376f6b15a6900b264e8b4d99e7b186a
tree61a654a3729424bf2f67589221cc440489c1092a
parentede0017eb9e72cb5a799ad000ebe45cf326524d6
signaturelock-open Commit is signed but in an unrecognized format.

std.posix.test: fix `dl_iterate_phdr` test

The old test was relying on the following properties: * There is a segment containing the ehdr, i.e. whose file offset is 0 * That segment is the first phdr with type `PT_LOAD`; because `PT_LOAD` segments are sorted on `p_vaddr`, this means its virtual address is the lowest of all loadable segments The first assumption, although not standard, is somewhat reasonable, and the commit prior to this one makes `Elf2` obey it. However, the second assumption is not based on anything, and to my knowledge the linker is entirely welcome to lay out the virtual address space as it sees fit. Therefore, refactor this test to eliminate that bad assumption.

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

lib/std/posix/test.zig+16-25
...@@ -64,42 +64,33 @@ const have_dl_phdr_info = posix.system.dl_phdr_info != void;...@@ -64,42 +64,33 @@ const have_dl_phdr_info = posix.system.dl_phdr_info != void;
64const dl_phdr_info = if (have_dl_phdr_info) posix.dl_phdr_info else anyopaque;64const dl_phdr_info = if (have_dl_phdr_info) posix.dl_phdr_info else anyopaque;
6565
66const IterFnError = error{66const IterFnError = error{
67 MissingPtLoadSegment,67 MissingLoadSegment,
68 MissingLoad,68 MissingEhdrLoadSegment,
69 BadElfMagic,69 BadElfMagic,
70 FailedConsistencyCheck,70 PhnumMismatch,
71};71};
7272
73fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {73fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
74 _ = size;74 _ = size;
75 // Count how many libraries are loaded75 // Count how many libraries are loaded
76 counter.* += @as(usize, 1);76 counter.* += 1;
7777
78 // The image should contain at least a PT.LOAD segment78 // The image should contain at least one loadable segment
79 if (info.phnum < 1) return error.MissingPtLoadSegment;79 if (info.phnum < 1) return error.MissingLoadSegment;
80
81 // Quick & dirty validation of the phdr pointers, make sure we're not
82 // pointing to some random gibberish
83 var i: usize = 0;
84 var found_load = false;
85 while (i < info.phnum) : (i += 1) {
86 const phdr = info.phdr[i];
8780
81 // For some quick and dirty validation, find the phdr which contains the ELF
82 // header, and check it makes sense.
83 for (info.phdr[0..info.phnum]) |phdr| {
88 if (phdr.type != .LOAD) continue;84 if (phdr.type != .LOAD) continue;
8985 if (phdr.offset != 0) continue;
90 const reloc_addr = info.addr + phdr.vaddr;86 // This segment holds the ELF header at the start
91 // Find the ELF header87 const ehdr: *elf.Ehdr = @ptrFromInt(info.addr + phdr.vaddr);
92 const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.offset));88 if (!mem.eql(u8, ehdr.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic;
93 // Validate the magic89 if (ehdr.e_phnum != info.phnum) return error.PhnumMismatch;
94 if (!mem.eql(u8, elf_header.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic;
95 // Consistency check
96 if (elf_header.e_phnum != info.phnum) return error.FailedConsistencyCheck;
97
98 found_load = true;
99 break;90 break;
91 } else {
92 return error.MissingEhdrLoadSegment;
100 }93 }
101
102 if (!found_load) return error.MissingLoad;
103}94}
10495
105test "dl_iterate_phdr" {96test "dl_iterate_phdr" {