{"record":{"id":"1cd47e3ed04a4395","repo":"can1357/oh-my-pi","slug":"invalid-rpm-package-string-tag-tag-has-an-inva","errorCode":null,"errorMessage":"Invalid RPM package: string tag ${tag} has an invalid count","messagePattern":"Invalid RPM package: string tag (.+?) has an invalid count","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/rpm.ts","lineNumber":94,"sourceCode":"\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;\n\t\t\tconst limit = indexSize + intro.dataSize;\n\t\t\tfor (let stringIndex = 0; stringIndex < stringCount; stringIndex++) {\n\t\t\t\twhile (cursor < limit && body[cursor] !== 0) cursor++;\n\t\t\t\tif (cursor === limit) {\n\t\t\t\t\tthrow new ArchiveError(`Invalid RPM package: string tag ${tag} is not NUL-terminated`);\n\t\t\t\t}\n\t\t\t\tcursor++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tthrow new ArchiveError(`Invalid RPM package: tag ${tag} uses unknown data type ${type}`);\n\t\t}\n\t\tif (offset % elementSize !== 0) throw new ArchiveError(`Invalid RPM package: tag ${tag} data is misaligned`);","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/rpm.ts#L76-L112","documentation":"RPM header entries of type RPM_TYPE_STRING (6) represent exactly one string, and the spec requires their count field to be 1. This parser enforces that invariant when validating the header body (signature or main header) via validateHeaderBody. If a STRING-tagged index entry declares count != 1, the package header is malformed or corrupted, so parsing aborts rather than reading a bogus value.","triggerScenarios":"readRpm() (or readRpmArchive/parseMainHeader) encounters an index entry with type === 6 whose count field is 0 or >= 2. This can come from a hand-edited or corrupt .rpm, a truncated/garbled download, or a file that is not really an RPM but happens to pass the lead magic sniff.","commonSituations":"Corrupted or partially downloaded .rpm files; fuzzed/malicious packages; hand-crafted headers from custom build tooling that writes wrong count fields; misidentified archives fed to the RPM reader.","solutions":["Re-download or rebuild the .rpm package; the file bytes are corrupt or non-conformant.","Verify the file with an independent tool (e.g. `rpm -qp <file>`) to confirm whether the header is genuinely malformed.","If the package is produced by your own tooling, fix it to emit count=1 for STRING (type 6) tags.","Catch ArchiveError around readRpm and treat the file as an unsupported/invalid archive instead of crashing."],"exampleFix":"// before: calling readRpm on a suspect file directly\nconst entries = await readRpm(source, options);\n// after: validate and handle gracefully\nimport { sniffRpm } from \"@oh-my-pi/pi-utils/ar/rpm\";\nif (!sniffRpm(leadBytes)) throw new Error(\"not an RPM\");\ntry {\n  const entries = await readRpm(source, options);\n} catch (err) {\n  if (err instanceof ArchiveError) return rejectPackage(err.message);\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"if (!sniffRpm(leadBytes)) throw new Error(\"not an RPM file\"); // otherwise no cheap pre-check: the count field lives inside the binary header","typeGuard":null,"tryCatchPattern":"try {\n  const entries = await readRpm(source, options);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"invalid count\")) {\n    return { ok: false, reason: \"corrupt RPM header\" };\n  }\n  throw err;\n}","preventionTips":["Download packages over verified channels and check checksums/signatures before parsing.","Pre-screen files with sniffRpm before invoking readRpm.","Do not hand-edit .rpm files; rebuild with rpmbuild instead."],"tags":["rpm","archive","corrupt-file","header-validation"],"backgroundTag":"rpm-header-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}