MuntashirAkon/AppManager · error · IOException

Paxheader value size

Error message

Paxheader value size ${restLen} exceeds size of header record

What it means

Thrown by TarUtils.parsePaxHeaders when a PAX extended header record declares a keyword/value whose remaining length (restLen) is larger than the bytes actually available in the header record (headerSize - totalRead). The library detects that the PAX record would overrun its containing 512-byte record block, i.e. a corrupt or maliciously crafted archive.

Solutions

  1. Verify archive integrity (checksum, re-download/re-transfer the tar file)
  2. Re-pack the archive with a standard tool: tar --format=pax or GNU tar, avoiding hand-edited PAX headers
  3. If producing archives yourself, use TarArchiveOutputStream rather than hand-writing PAX records
  4. Catch IOException and reject the archive as malformed
Defensive patterns

Strategy: try-catch

Validate before calling

if (!archiveFile.isFile() || archiveFile.length() == 0) throw new IOException("archive missing or empty");

Try / catch

try (TarArchiveInputStream in = new TarArchiveInputStream(fis)) {
    // read entries
} catch (IOException e) {
    if (e.getMessage().contains("exceeds size of header record")) {
        throw new CorruptArchiveException("Malformed PAX header record", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Reading a TAR entry whose PAX header contains a record where the declared length field points past the end of the current header record; typically corrupt data or a deliberately malformed file (CVE-hardening check).

Common situations: Opening archives produced by broken writers, files truncated/modified in transit, or fuzzed/test corpus archives with inconsistent PAX length fields.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/3eab934fc5741568. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java:709

                if (ch == '\n') { // blank line in header
                    break;
                } else if (ch == ' '){ // End of length string
                    // Get keyword
                    final ByteArrayOutputStream coll = new ByteArrayOutputStream();
                    while((ch = inputStream.read()) != -1) {
                        read++;
                        totalRead++;
                        if (totalRead < 0 || (headerSize >= 0 && totalRead >= headerSize)) {
                             break;
                         }
                        if (ch == '='){ // end of keyword
                            final String keyword = coll.toString(CharsetNames.UTF_8);
                            // Get rest of entry
                            final int restLen = len - read;
                            if (restLen <= 1) { // only NL
                                headers.remove(keyword);
                            } else if (headerSize >= 0 && restLen > headerSize - totalRead) {
                                throw new IOException("Paxheader value size " + restLen
                                    + " exceeds size of header record");

                            } else {
                                final byte[] rest = new byte[restLen];
                                final int got = IOUtils.readFully(inputStream, rest);
                                if (got != restLen) {
                                    throw new IOException("Failed to read "
                                            + "Paxheader. Expected "
                                            + restLen
                                            + " bytes, read "
                                            + got);
                                }
                                totalRead += restLen;
                                // Drop trailing NL
                                if (rest[restLen - 1] != '\n') {
                                    throw new IOException("Failed to read Paxheader."
                                       + "Value should end with a newline");
                                }

View on GitHub (pinned to 0152f468fc)