{"record":{"id":"f67404801c6bd1a1","repo":"jdx/mise","slug":"elf-uses-pn-xnum-program-header-counts","errorCode":null,"errorMessage":"ELF uses PN_XNUM program header counts","messagePattern":"ELF uses PN_XNUM program header counts","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/elf.rs","lineNumber":117,"sourceCode":"#[derive(Clone, Copy)]\nstruct Phdr {\n    p_type: u32,\n    p_offset: u64,\n    p_vaddr: u64,\n    p_filesz: u64,\n    p_memsz: u64,\n    p_align: u64,\n}\n\nfn read_phdrs(content: &[u8]) -> Result<Vec<Phdr>> {\n    let e_phoff = rd_u64(content, 32)? as usize;\n    let e_phentsize = rd_u16(content, 54)? as usize;\n    let e_phnum = rd_u16(content, 56)? as usize;\n    if e_phentsize != PHDR_SIZE {\n        bail!(\"unexpected ELF e_phentsize {e_phentsize}\");\n    }\n    if e_phnum >= 0xffff {\n        bail!(\"ELF uses PN_XNUM program header counts\");\n    }\n    let mut phdrs = Vec::with_capacity(e_phnum);\n    for i in 0..e_phnum {\n        let off = e_phoff + i * PHDR_SIZE;\n        phdrs.push(Phdr {\n            p_type: rd_u32(content, off)?,\n            p_offset: rd_u64(content, off + 8)?,\n            p_vaddr: rd_u64(content, off + 16)?,\n            p_filesz: rd_u64(content, off + 32)?,\n            p_memsz: rd_u64(content, off + 40)?,\n            p_align: rd_u64(content, off + 48)?,\n        });\n    }\n    Ok(phdrs)\n}\n\nfn vaddr_to_offset(phdrs: &[Phdr], vaddr: u64) -> Option<usize> {\n    phdrs","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/elf.rs#L99-L135","documentation":"ELF's extended section numbering (PN_XNUM) stores the real program header count in section header 0 rather than e_phnum, and e_phnum then holds the escape value 0xffff. This parser does not implement PN_XNUM, so any binary reporting e_phnum >= 0xffff is rejected rather than misparsed. Such binaries are extremely rare (they need ~65k program headers).","triggerScenarios":"Calling elf::patch or read_linkage on an ELF whose e_phnum field is 0xffff or larger, i.e. a PN_XNUM-encoded binary or a corrupted file with a garbage program-header count.","commonSituations":"Processing machine-generated or fuzzed binaries; a corrupted bottle; (rarely) a deliberately huge binary built with tens of thousands of segments that uses extended numbering.","solutions":["Confirm the binary is not corrupted (readelf -h shows a sane program header count); re-extract if corrupted.","For genuine PN_XNUM binaries, fall back to an external tool (patchelf) instead of this parser.","Skip patching such files and record them as unsupported in the relocation flow."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"let e_phnum = u16::from_le_bytes([content[56], content[57]]);\nif e_phnum >= 0xffff { /* PN_XNUM binary: skip or use external patchelf */ }","typeGuard":"fn uses_pn_xnum(elf: &[u8]) -> bool {\n    elf.len() > 58 && u16::from_le_bytes([elf[56], elf[57]]) == 0xffff\n}","tryCatchPattern":"match read_phdrs(&content) {\n    Err(e) if e.to_string().contains(\"PN_XNUM\") => {\n        // route to patchelf or skip with a recorded warning\n    }\n    other => other?,\n}","preventionTips":["Reject or route out binaries with extended section numbering before calling the patcher.","Validate bottle checksums to catch corruption that garbles e_phnum.","Keep the relocation pipeline best-effort: log and skip unsupported ELF shapes."],"tags":["elf","binary-parsing","pn-xnum","unsupported-format"],"backgroundTag":"unsupported-operation","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}