{"record":{"id":"2451118ca771cd1d","repo":"can1357/oh-my-pi","slug":"invalid-rpm-package-tag-tag-points-outside-hea","errorCode":null,"errorMessage":"Invalid RPM package: tag ${tag} points outside header data","messagePattern":"Invalid RPM package: tag (.+?) points outside header data","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/rpm.ts","lineNumber":81,"sourceCode":"\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;\n\t\telse if (type === 4) elementSize = 4;\n\t\telse if (type === 5) elementSize = 8;\n\t\telse if (type === 0) {\n\t\t\tif (count !== 0) throw new ArchiveError(`Invalid RPM package: null tag ${tag} has values`);\n\t\t\tcontinue;\n\t\t} else if (type === RPM_TYPE_STRING || type === 8 || type === 9) {\n\t\t\tconst stringCount = type === RPM_TYPE_STRING ? 1 : count;\n\t\t\tif (type === RPM_TYPE_STRING && count !== 1) {\n\t\t\t\tthrow new ArchiveError(`Invalid RPM package: string tag ${tag} has an invalid count`);\n\t\t\t}\n\t\t\tif (stringCount > remaining) {\n\t\t\t\tthrow new ArchiveError(`Invalid RPM package: string tag ${tag} exceeds header data`);\n\t\t\t}\n\t\t\tlet cursor = indexSize + offset;","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/rpm.ts#L63-L99","documentation":"ArchiveError thrown by validateHeaderBody() while iterating index entries: an entry's data offset exceeds intro.dataSize, meaning the tag claims to point outside the header's data area. Prevents out-of-bounds reads when decoding tag values.","triggerScenarios":"Header index entry whose offset field (readUInt32BE at recordOffset+8) is greater than dataSize — corrupt or forged header entries.","commonSituations":"Corrupted downloads, hand-modified packages, fuzzed/malicious RPMs designed to cause OOB reads.","solutions":["Re-download the package from a trusted mirror","Verify package checksum/signature before parsing","If you build RPMs programmatically, ensure index offsets stay within dataSize"],"exampleFix":"// before\n// trusting offsets from an untrusted header\nawait readRpmArchive(buffer);\n// after\nassertRpmChecksumMatches(buffer); // verify integrity first\nawait readRpmArchive(buffer);","handlingStrategy":"try-catch","validationCode":"if (!await verifyRpmSignature(path)) throw new Error('untrusted rpm: bad signature');","typeGuard":"null","tryCatchPattern":"try {\n  const rpm = await readRpmArchive(buf);\n} catch (err) {\n  if (err instanceof ArchiveError && /tag \\d+ points outside header data/.test(err.message)) {\n    // reject as corrupt/forged header\n  } else throw err;\n}","preventionTips":["Verify package signatures/checksums before parsing","Never parse RPMs from untrusted upload endpoints without sandboxing","Regenerate packages whose headers were hand-edited"],"tags":["rpm","archive","bounds-check","corrupt-file"],"backgroundTag":"archive-index-out-of-bounds","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}