From 29bcd2d54376f6b15a6900b264e8b4d99e7b186a Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 15 Aug 2026 09:04:07 +0100 Subject: [PATCH] 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. --- lib/std/posix/test.zig | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 4fb68855b5a5953b709fae4f893bc051a50dbf09..93d83d381df952dfc923628006a8eaa1aeced8a7 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -64,42 +64,33 @@ const have_dl_phdr_info = posix.system.dl_phdr_info != void; const dl_phdr_info = if (have_dl_phdr_info) posix.dl_phdr_info else anyopaque; const IterFnError = error{ - MissingPtLoadSegment, - MissingLoad, + MissingLoadSegment, + MissingEhdrLoadSegment, BadElfMagic, - FailedConsistencyCheck, + PhnumMismatch, }; fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void { _ = size; // Count how many libraries are loaded - counter.* += @as(usize, 1); + counter.* += 1; - // The image should contain at least a PT.LOAD segment - if (info.phnum < 1) return error.MissingPtLoadSegment; - - // Quick & dirty validation of the phdr pointers, make sure we're not - // pointing to some random gibberish - var i: usize = 0; - var found_load = false; - while (i < info.phnum) : (i += 1) { - const phdr = info.phdr[i]; + // The image should contain at least one loadable segment + if (info.phnum < 1) return error.MissingLoadSegment; + // For some quick and dirty validation, find the phdr which contains the ELF + // header, and check it makes sense. + for (info.phdr[0..info.phnum]) |phdr| { if (phdr.type != .LOAD) continue; - - const reloc_addr = info.addr + phdr.vaddr; - // Find the ELF header - const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.offset)); - // Validate the magic - if (!mem.eql(u8, elf_header.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic; - // Consistency check - if (elf_header.e_phnum != info.phnum) return error.FailedConsistencyCheck; - - found_load = true; + if (phdr.offset != 0) continue; + // This segment holds the ELF header at the start + const ehdr: *elf.Ehdr = @ptrFromInt(info.addr + phdr.vaddr); + if (!mem.eql(u8, ehdr.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic; + if (ehdr.e_phnum != info.phnum) return error.PhnumMismatch; break; + } else { + return error.MissingEhdrLoadSegment; } - - if (!found_load) return error.MissingLoad; } test "dl_iterate_phdr" { -- 2.54.0