{"record":{"id":"1f232e6854a7da08","repo":"can1357/oh-my-pi","slug":"invalid-arj-extended-header-crc32","errorCode":null,"errorMessage":"Invalid ARJ extended header CRC32","messagePattern":"Invalid ARJ extended header CRC32","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/arj.ts","lineNumber":86,"sourceCode":"\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\n\tread(count: number): number {\n\t\tif (!Number.isInteger(count) || count < 0 || count > 24 || this.#position + count > this.#bytes.byteLength * 8) {\n\t\t\tthrow new ArchiveError(\"Invalid ARJ method-4 compressed data: truncated bitstream\");","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/arj.ts#L68-L104","documentation":"Like basic headers, each ARJ extended header carries a CRC-32 over its payload, stored after the payload. parseArjBlock computes crc32 over the extension bytes and compares against the trailing u32; a mismatch means that extension's bytes are corrupted, so parsing stops rather than consuming untrusted extended metadata.","triggerScenarios":"During the extended-header walk in parseArjBlock: crc32(bytes[cursor..cursor+extensionSize]) differs from the u32 at cursor+extensionSize. Caused by byte corruption inside an extended header or a wrong extensionSize making the reader hash/verify the wrong region.","commonSituations":"Damaged downloads/media, archives modified by tools that rewrite extended headers (comments, timestamps, GOST/MD5 data) without recomputing their CRCs, or a corrupted chain where an earlier wrong size desynchronizes the CRC check of the next extension.","solutions":["Test externally (`arj t` / 7-Zip) to confirm damage; restore the archive from backup or re-download.","Identify which tool created/modified the file; re-create the archive with the original tool and default options.","Re-pack the archive: extract what an external tolerant tool can, then rebuild it so all CRCs are recomputed.","If writing ARJ files yourself, CRC-32 every extended-header payload and append it little-endian after the payload."],"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(\"extended header CRC32\")) {\n    // extended metadata is damaged; re-obtain or re-pack the archive\n    throw new Error(`ARJ extended header corrupt in ${sourceName}`);\n  }\n  throw err;\n}","preventionTips":["Re-pack archives modified by third-party tools so all CRCs are regenerated.","Verify binary-safe transfer with checksums before parsing.","Run `arj t` / 7-Zip tests as a pre-parse gate on untrusted files."],"tags":["archive","checksum","crc32","corrupt-file"],"backgroundTag":"archive-checksum-mismatch","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}