{"record":{"id":"df1661b1b96816f0","repo":"github/copilot-sdk","slug":"program-header-table-offset-outside-probe-window","errorCode":null,"errorMessage":"Program header table offset outside probe window: + phoff","messagePattern":"Program header table offset outside probe window: \\+ phoff","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/ffi/PlatformDetector.java","lineNumber":199,"sourceCode":"        int phentsize;\n        int phnum;\n        int minimumPhentsize;\n        if (elfClass == ELF_CLASS_64) {\n            phoff = readUInt64(probe, 32, littleEndian);\n            phentsize = readUInt16(probe, 54, littleEndian);\n            phnum = readUInt16(probe, 56, littleEndian);\n            minimumPhentsize = ELF64_PROGRAM_HEADER_SIZE;\n        } else if (elfClass == ELF_CLASS_32) {\n            phoff = readUInt32(probe, 28, littleEndian);\n            phentsize = readUInt16(probe, 42, littleEndian);\n            phnum = readUInt16(probe, 44, littleEndian);\n            minimumPhentsize = ELF32_PROGRAM_HEADER_SIZE;\n        } else {\n            throw new IOException(\"Unsupported ELF class: \" + elfClass);\n        }\n\n        if (phoff < 0 || phoff >= size) {\n            throw new IOException(\"Program header table offset outside probe window: \" + phoff);\n        }\n        if (phentsize < minimumPhentsize || phnum <= 0) {\n            throw new IOException(\"Invalid ELF program header metadata: phentsize=\" + phentsize + \", phnum=\" + phnum);\n        }\n\n        for (int i = 0; i < phnum; i++) {\n            long baseLong = phoff + ((long) i * phentsize);\n            if (baseLong < 0 || baseLong > Integer.MAX_VALUE) {\n                break;\n            }\n            int base = (int) baseLong;\n            if (base + phentsize > size) {\n                break;\n            }\n\n            long pType = readUInt32(probe, base, littleEndian);\n            if (pType != PT_INTERP) {\n                continue;","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/ffi/PlatformDetector.java#L181-L217","documentation":"The parsed e_phoff (program header table offset) must fall inside the probe bytes actually read from the file. If it is negative or beyond the probe window, the ELF header is corrupt or the probe is truncated relative to what the header claims, so parsing cannot continue and an IOException is thrown.","triggerScenarios":"e_phoff parsed from the header exceeds the probe length (probe smaller than the header promises, e.g. a truncated read of a large binary) or the header itself is corrupt, yielding a negative/absurd offset.","commonSituations":"Reading only the first N bytes of a large statically linked binary whose program header table sits beyond the probe; corrupted binaries with garbage e_phoff; partial downloads.","solutions":["Increase the probe size so it covers the program header table (e.g. 4096 bytes or more, or read the first min(fileSize, 64KiB)).","Verify the binary with `readelf -l <path>` — if readelf shows a sane program header table, your probe is too small; if not, the file is corrupt.","Re-download/reinstall the binary and check its checksum.","Confirm the probe was read from offset 0 of the actual file (not a re-based slice)."],"exampleFix":"// before\nbyte[] probe = new byte[256];\nreadFully(path, probe);\nString interp = readElfPtInterp(probe);\n// after\nbyte[] probe = Files.readAllBytes(path); // or a 64KiB head-read\nString interp = readElfPtInterp(probe);","handlingStrategy":"validation","validationCode":"// Ensure the probe covers the program header table\nlong fileSize = Files.size(path);\nbyte[] probe = readHead(path, (int) Math.min(fileSize, 65536));\n// probe.length must exceed any plausible e_phoff + phentsize*phnum","typeGuard":null,"tryCatchPattern":"try {\n    String interp = readElfPtInterp(probe);\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Program header table offset outside\")) {\n        probe = Files.readAllBytes(path); // retry with the full file\n        interp = readElfPtInterp(probe);\n    } else throw e;\n}","preventionTips":["Read a large head slice (>= 64KiB) or the whole file instead of tiny fixed probes.","Validate binaries with `readelf -l <path>` during packaging.","Check file completeness (size + checksum) after download.","Start probes at file offset 0 of the real file."],"tags":["elf","binary-parsing","file-io","java"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}