{"record":{"id":"8dbe4cf49464918e","repo":"can1357/oh-my-pi","slug":"invalid-arj-archive-too-many-extended-headers","errorCode":null,"errorMessage":"Invalid ARJ archive: too many extended headers","messagePattern":"Invalid ARJ archive: too many extended headers","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/arj.ts","lineNumber":83,"sourceCode":"\t}\n\tconst bodySize = u16(bytes, offset + 2);\n\tif (bodySize === 0)\n\t\treturn { bodyStart: offset + 4, bodySize: 0, nextOffset: offset + 4, metadataSize: 4, isEnd: true };\n\tif (bodySize < 30 || bodySize > ARJ_MAX_BASIC_HEADER) throw new ArchiveError(\"Invalid ARJ basic header size\");\n\tconst bodyStart = offset + 4;\n\tconst bodyEnd = bodyStart + bodySize;\n\tassertRange(bytes, bodyStart, bodyEnd + 4, \"basic header\");\n\tif (crc32(bytes.subarray(bodyStart, bodyEnd)) !== u32(bytes, bodyEnd)) {\n\t\tthrow new ArchiveError(\"Invalid ARJ basic header CRC32\");\n\t}\n\tlet cursor = bodyEnd + 4;\n\tlet extensionCount = 0;\n\tfor (;;) {\n\t\tassertRange(bytes, cursor, cursor + 2, \"extended header size\");\n\t\tconst extensionSize = u16(bytes, cursor);\n\t\tcursor += 2;\n\t\tif (extensionSize === 0) break;\n\t\tif (++extensionCount > 65_535) throw new ArchiveError(\"Invalid ARJ archive: too many extended headers\");\n\t\tassertRange(bytes, cursor, cursor + extensionSize + 4, \"extended header\");\n\t\tif (crc32(bytes.subarray(cursor, cursor + extensionSize)) !== u32(bytes, cursor + extensionSize)) {\n\t\t\tthrow new ArchiveError(\"Invalid ARJ extended header CRC32\");\n\t\t}\n\t\tcursor += extensionSize + 4;\n\t\tassertIndexSize(cursor - offset, options.limits, \"header metadata\");\n\t}\n\treturn { bodyStart, bodySize, nextOffset: cursor, metadataSize: cursor - offset, isEnd: false };\n}\n\nclass ArjBitReader {\n\treadonly #bytes: Uint8Array;\n\t#position = 0;\n\n\tconstructor(bytes: Uint8Array) {\n\t\tthis.#bytes = bytes;\n\t}\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/arj.ts#L65-L101","documentation":"ARJ headers may be followed by a chain of extended headers, each a 16-bit size (0 terminates the chain). This reader caps the chain at 65,535 entries; exceeding that means the loop is not finding its terminator and would run unboundedly over the buffer, so it throws to bound work on malformed input.","triggerScenarios":"parseArjBlock() walks 65,536+ non-zero extension sizes without hitting a 0 u16 — a corrupt or malicious archive whose extended-header chain never terminates, or garbage after the basic header interpreted as extension sizes.","commonSituations":"Fuzzed/attacker-crafted archives (this cap is a DoS guard), a corrupted file where the terminating 0x0000 was overwritten, or bytes after the basic header belonging to a different structure because the header size itself was wrong.","solutions":["Treat the file as malicious or severely corrupt: do not attempt repair; obtain the archive from a trusted source.","Confirm with an external test (`arj t`) whether the archive is otherwise valid; if not, discard it.","If you produce ARJ files, always terminate the extended-header chain with a 0x0000 size word before the next block.","Keep the library's limits (options.limits) in place — do not raise them to 'make the file parse'; this error indicates malformed structure, not a too-small budget."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return readArj(data, options);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"too many extended headers\")) {\n    // treat as malformed/hostile input: reject outright\n    throw new Error(\"ARJ rejected: extended-header chain does not terminate\");\n  }\n  throw err;\n}","preventionTips":["Treat this error as a sign of a malicious or badly corrupt archive — never raise limits to work around it.","Validate untrusted archives out-of-process or with timeouts so malformed input cannot stall pipelines.","Ensure any ARJ writer you use terminates extended-header chains with a 0x0000 size."],"tags":["archive","malicious-input","corrupt-file","limits"],"backgroundTag":"unterminated-header-chain","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}