{"record":{"id":"ed9d0f7760c58afc","repo":"can1357/oh-my-pi","slug":"invalid-rpm-package-what-header-is-too-large","errorCode":null,"errorMessage":"Invalid RPM package: ${what} header is too large","messagePattern":"Invalid RPM package: (.+?) header is too large","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/rpm.ts","lineNumber":67,"sourceCode":"\t}\n\tconst bytes = await source.read(start, end);\n\tif (bytes.byteLength !== end - start) throw new ArchiveError(`Invalid RPM package: truncated ${what}`);\n\treturn bytes;\n}\n\nfunction parseHeaderIntro(bytes: Uint8Array, options: FormatReadOptions, what: string): HeaderIntro {\n\tif (bytes.byteLength !== RPM_HEADER_INTRO_SIZE || readUInt32BE(bytes, 0) !== RPM_HEADER_MAGIC) {\n\t\tthrow new ArchiveError(`Invalid RPM package: corrupt ${what} header magic`);\n\t}\n\tfor (let offset = 4; offset < 8; offset++) {\n\t\tif (bytes[offset] !== 0) throw new ArchiveError(`Invalid RPM package: corrupt ${what} header reserved bytes`);\n\t}\n\tconst indexCount = readUInt32BE(bytes, 8);\n\tconst dataSize = readUInt32BE(bytes, 12);\n\tassertEntryCount(indexCount, options.limits);\n\tconst indexSize = indexCount * RPM_INDEX_ENTRY_SIZE;\n\tconst bodySize = indexSize + dataSize;\n\tif (!Number.isSafeInteger(bodySize)) throw new ArchiveError(`Invalid RPM package: ${what} header is too large`);\n\tassertIndexSize(RPM_HEADER_INTRO_SIZE + bodySize, options.limits, `RPM ${what} header`);\n\treturn { indexCount, dataSize, bodySize, totalSize: RPM_HEADER_INTRO_SIZE + bodySize };\n}\n\nfunction validateHeaderBody(body: Uint8Array, intro: HeaderIntro, what: string): void {\n\tconst indexSize = intro.indexCount * RPM_INDEX_ENTRY_SIZE;\n\tif (body.byteLength !== intro.bodySize) throw new ArchiveError(`Invalid RPM package: truncated ${what} header`);\n\tfor (let index = 0; index < intro.indexCount; index++) {\n\t\tconst recordOffset = index * RPM_INDEX_ENTRY_SIZE;\n\t\tconst tag = readUInt32BE(body, recordOffset);\n\t\tconst type = readUInt32BE(body, recordOffset + 4);\n\t\tconst offset = readUInt32BE(body, recordOffset + 8);\n\t\tconst count = readUInt32BE(body, recordOffset + 12);\n\t\tif (offset > intro.dataSize) throw new ArchiveError(`Invalid RPM package: tag ${tag} points outside header data`);\n\t\tconst remaining = intro.dataSize - offset;\n\t\tlet elementSize = 0;\n\t\tif (type === 1 || type === 2 || type === 7) elementSize = 1;\n\t\telse if (type === 3) elementSize = 2;","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/rpm.ts#L49-L85","documentation":"ArchiveError thrown by parseHeaderIntro() when indexCount * RPM_INDEX_ENTRY_SIZE + dataSize (bodySize) is not a safe integer — the header declares an absurdly large size. After the count is checked against options.limits via assertEntryCount, this catches numeric overflow of the combined body size before any allocation/read.","triggerScenarios":"A corrupt or malicious header declaring indexCount/dataSize values so large their sum exceeds Number.MAX_SAFE_INTEGER; also header sizes exceeding limits enforced by assertIndexSize right after.","commonSituations":"Maliciously crafted .rpm files (zip-bomb-style headers), corrupted binaries, random bytes that happen to pass the magic check.","solutions":["Re-download the package from a trusted source","Verify checksums/signatures before parsing untrusted RPMs","If parsing your own archives, ensure header indexCount/dataSize are within limits"],"exampleFix":"// before\nawait readRpmArchive(untrustedBuffer);\n// after\nif (!trustedChecksum(untrustedBuffer)) throw new Error('untrusted rpm');\nawait readRpmArchive(untrustedBuffer);","handlingStrategy":"validation","validationCode":"if (buf.byteLength > MAX_EXPECTED_RPM_SIZE) throw new Error('rpm implausibly large');\nif (!trustedSource(buf)) throw new Error('refusing to parse untrusted rpm');","typeGuard":"null","tryCatchPattern":"try {\n  const rpm = await readRpmArchive(buf);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes('header is too large')) {\n    // treat as malformed/malicious input; reject\n  } else throw err;\n}","preventionTips":["Only parse RPMs from trusted sources; verify signatures","Pass sane FormatReadOptions limits to the reader","Cap input file size before parsing untrusted archives"],"tags":["rpm","archive","malicious-input","limits"],"backgroundTag":"archive-header-too-large","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}