{"record":{"id":"44c1deea1f3f651d","repo":"can1357/oh-my-pi","slug":"invalid-label-compressed-data-history-distance","errorCode":null,"errorMessage":"Invalid ${label} compressed data: history distance is out of range","messagePattern":"Invalid (.+?) compressed data: history distance is out of range","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/lzh.ts","lineNumber":235,"sourceCode":"\t\t}\n\t\tblockRemaining--;\n\t\tconst symbol = commands!.decode(reader);\n\t\tif (symbol < 256) {\n\t\t\toutput[outputPosition++] = symbol;\n\t\t\tcontinue;\n\t\t}\n\t\tconst length = symbol - 256 + 3;\n\t\tif (length > outSize - outputPosition) {\n\t\t\tthrow new ArchiveError(`Invalid ${label} compressed data: match exceeds declared size`);\n\t\t}\n\t\tconst positionCode = positions!.decode(reader);\n\t\tlet distance = positionCode;\n\t\tif (positionCode > 1) {\n\t\t\tconst lowBitCount = positionCode - 1;\n\t\t\tdistance = 2 ** lowBitCount + reader.read(lowBitCount);\n\t\t}\n\t\tif (distance >= dictionarySize || distance >= outputPosition) {\n\t\t\tthrow new ArchiveError(`Invalid ${label} compressed data: history distance is out of range`);\n\t\t}\n\t\tlet sourcePosition = outputPosition - distance - 1;\n\t\tfor (let index = 0; index < length; index++) output[outputPosition++] = output[sourcePosition++]!;\n\t}\n\tif (blockRemaining !== 0) throw new ArchiveError(`Invalid ${label} compressed data: block exceeds declared size`);\n\treader.assertZeroPadding();\n\treturn output;\n}\n\nfunction decompressLzs(packed: Uint8Array, outSize: number): Uint8Array {\n\tconst reader = new MsbBitReader(packed, \"LZH -lzs-\");\n\tconst output = new Uint8Array(outSize);\n\tconst history = new Uint8Array(2048);\n\thistory.fill(0x20);\n\tlet historyPosition = 2048 - 17;\n\tlet outputPosition = 0;\n\tconst emit = (value: number): void => {\n\t\tif (outputPosition >= outSize) throw new ArchiveError(\"Invalid LZH -lzs- data: output exceeds declared size\");","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/lzh.ts#L217-L253","documentation":"A match's distance (back-reference offset) must be smaller than both the dictionary size and the bytes already emitted; otherwise it would read before the start of the output. This indicates corrupt position data.","triggerScenarios":"decompressLhStatic decodes a position symbol plus low bits whose distance >= dictionarySize or >= bytes written so far — corrupt stream, wrong dictionarySize for the method, or output starting mid-stream so outputPosition is too small for early references.","commonSituations":"Wrong dictionary size parameter (e.g. 4KB for -lh5- data that needs larger); misparsed extended headers shifting stream start; fuzzed archives.","solutions":["Pass the correct dictionarySize for the method variant","Ensure decompression starts at the true beginning of the member's compressed data","Re-validate/re-download the archive","Catch ArchiveError for untrusted input"],"exampleFix":"// before\ndecompressLhStatic(packed, outSize, 5, 256, \"LZH -lh5-\"); // dictionary 4KB\n// after\n// -lh6-/-lh7- use larger dictionaries\ndecompressLhStatic(packed, outSize, 6, 8192, \"LZH -lh6-\");","handlingStrategy":"try-catch","validationCode":"// dictionarySize must match the method; check it is a power-of-two-ish sane value\nif (dictionarySize <= 0 || !Number.isSafeInteger(dictionarySize)) throw new Error(\"bad dictionary size\");","typeGuard":null,"tryCatchPattern":"try {\n  const out = decompressLhStatic(packed, outSize, positionBits, positionSymbols, label);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"distance\")) return null;\n  throw err;\n}","preventionTips":["Match dictionarySize to the method variant (-lh5- 4KB, -lh6- 32KB, -lh7- 64KB)","Decompress from the member's true stream start","Validate archive integrity first"],"tags":["archive","corruption","lzh"],"backgroundTag":"corrupt-archive-data","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}