{"record":{"id":"42babacfc229ec0c","repo":"can1357/oh-my-pi","slug":"invalid-cab-archive-invalid-lzx-repeated-offset","errorCode":null,"errorMessage":"Invalid CAB archive: invalid LZX repeated offset","messagePattern":"Invalid CAB archive: invalid LZX repeated offset","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/lzx.ts","lineNumber":255,"sourceCode":"\t\t\t\tfor (let index = 0; index < alignedLengths.byteLength; index++) alignedLengths[index] = reader.readBits(3);\n\t\t\t\tthis.#alignedTable = new LzxHuffmanTable(alignedLengths);\n\t\t\t}\n\t\t\treadCodeLengths(reader, this.#mainLengths, 0, 256);\n\t\t\treadCodeLengths(reader, this.#mainLengths, 256, this.#mainLengths.byteLength);\n\t\t\tthis.#mainTable = new LzxHuffmanTable(this.#mainLengths);\n\t\t\tif (this.#mainLengths[0xe8] !== 0) this.#intelStarted = true;\n\t\t\treadCodeLengths(reader, this.#lengthLengths, 0, this.#lengthLengths.byteLength);\n\t\t\tthis.#lengthTable = new LzxHuffmanTable(this.#lengthLengths, true);\n\t\t\treturn;\n\t\t}\n\t\tif (this.#blockType === 3) {\n\t\t\tthis.#intelStarted = true;\n\t\t\treader.alignWord();\n\t\t\tthis.#r0 = reader.readUInt32LE();\n\t\t\tthis.#r1 = reader.readUInt32LE();\n\t\t\tthis.#r2 = reader.readUInt32LE();\n\t\t\tif (this.#r0 === 0 || this.#r1 === 0 || this.#r2 === 0) {\n\t\t\t\tthrow new ArchiveError(\"Invalid CAB archive: invalid LZX repeated offset\");\n\t\t\t}\n\t\t\tthis.#uncompressedPadding = (this.#blockLength & 1) !== 0;\n\t\t\treturn;\n\t\t}\n\t\tthrow new ArchiveError(`Invalid CAB archive: unsupported LZX block type ${this.#blockType}`);\n\t}\n\n\t#decodeRun(reader: LzxBitReader, output: Uint8Array, outputStart: number, count: number): number {\n\t\tif (this.#blockType === 3) {\n\t\t\tfor (let index = 0; index < count; index++) this.#writeByte(reader.readByte(), output, outputStart + index);\n\t\t\treturn count;\n\t\t}\n\t\tif (!this.#mainTable || !this.#lengthTable)\n\t\t\tthrow new ArchiveError(\"Invalid CAB archive: missing LZX decode trees\");\n\n\t\tlet produced = 0;\n\t\twhile (produced < count) {\n\t\t\tconst element = this.#mainTable.decode(reader);","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/lzx.ts#L237-L273","documentation":"During CAB LZX decompression, the decoder reads the three repeated-offset registers (r0/r1/r2) from the block header. The LZX spec requires all three to be initialized to 1 (nonzero); a zero value means the stream is corrupt or not real LZX data, so ArchiveError is thrown from #readBlockHeader.","triggerScenarios":"decompressFrame -> #readBlockHeader parses an LZX block whose header yields r0, r1, or r2 equal to 0 after reading three UInt32LE values.","commonSituations":"Corrupted or truncated .cab files, wrong offsets into the CAB data (parsing a folder that is not actually LZX-compressed), or hand-crafted/fuzzed archive bytes.","solutions":["Verify the CAB file is intact (re-download or re-extract the archive).","Confirm the folder's compression method is actually LZX and you are passing the correct data slice to decompressFrame.","Treat the file as corrupt: surface ArchiveError to the caller instead of retrying."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// heuristic pre-check: CAB folder payload should start with plausible LZX bitstream bytes\nfunction looksLikeLzxPayload(bytes, offset) {\n  return Number.isInteger(offset) && offset >= 0 && offset + 12 <= bytes.byteLength;\n}","typeGuard":"function hasLzxHeaderRoom(bytes, offset) {\n  return offset + 12 <= bytes.byteLength;\n}","tryCatchPattern":"try {\n  const out = folder.decompressFrame(frame);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"repeated offset\")) {\n    // report archive as corrupt\n  } else throw err;\n}","preventionTips":["Verify CAB integrity (checksums) before extraction","Ensure frames are decompressed sequentially from the first frame","Only pass LZX-compressed folder data to the LZX decoder"],"tags":["archive","cab","lzx","corrupt-data"],"backgroundTag":"corrupt-archive-data","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}