{"record":{"id":"44b5f98c405a8f98","repo":"can1357/oh-my-pi","slug":"corrupt-compress-z-dictionary-chain","errorCode":null,"errorMessage":"Corrupt compress (.Z) dictionary chain","messagePattern":"Corrupt compress \\(\\.Z\\) dictionary chain","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/lzw.ts","lineNumber":148,"sourceCode":"\t\t\treader.assertFinalPadding();\n\t\t\treturn output.finish();\n\t\t}\n\t\tif (code >= dictionaryHead) {\n\t\t\tthrow new ArchiveError(`Corrupt compress (.Z) dictionary code ${code}`);\n\t\t}\n\t\tif (blockMode && code === CLEAR_CODE) {\n\t\t\treader.alignCodeGroup(width);\n\t\t\twidth = MIN_BITS;\n\t\t\tdictionaryHead = FIRST_BLOCK_CODE;\n\t\t\tneedsPreviousSuffix = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet current = code;\n\t\tlet stackLength = 0;\n\t\twhile (current >= 256) {\n\t\t\tif (current >= dictionaryHead || stackLength >= stack.length - 1) {\n\t\t\t\tthrow new ArchiveError(\"Corrupt compress (.Z) dictionary chain\");\n\t\t\t}\n\t\t\tstack[stackLength++] = suffixes[current]!;\n\t\t\tcurrent = parents[current]!;\n\t\t}\n\t\tstack[stackLength++] = current;\n\n\t\tif (needsPreviousSuffix) {\n\t\t\tsuffixes[dictionaryHead - 1] = current;\n\t\t\tif (code === dictionaryHead - 1) {\n\t\t\t\tstack[0] = current;\n\t\t\t}\n\t\t}\n\t\toutput.appendReversed(stack, stackLength);\n\n\t\tif (dictionaryHead < dictionaryLimit) {\n\t\t\tneedsPreviousSuffix = true;\n\t\t\tparents[dictionaryHead++] = code;\n\t\t\tif (dictionaryHead > 2 ** width && width < maxBits) {","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/lzw.ts#L130-L166","documentation":"When expanding an LZW code into bytes, the decoder walks the parent chain of dictionary entries. This error means the chain walks into an undefined entry (>= dictionaryHead) or becomes pathologically long (stack overflow guard) — the dictionary tables are inconsistent, which can only happen with a corrupt or hostile bitstream (or an earlier decode desync).","triggerScenarios":"Decoding a .Z stream where a dictionary entry's parent points beyond dictionaryHead or a chain exceeds 2^maxBits - 1 links: bit-flipped payload, decoding from the wrong stream offset (desync), or adversarial input crafted to loop the chain.","commonSituations":"Corrupted archives from damaged storage/transfers; fuzz-tested inputs; decoding a stream that had earlier codes dropped or altered so subsequent entries were built from wrong data.","solutions":["Treat the archive as corrupt — restore from a known-good copy and verify checksums.","Ensure no bytes were inserted/removed before decoding (header stripped exactly 3 bytes, single stream).","Keep the provided maxOutput limit sane: raising it wildly does not fix this; the issue is input integrity, not limits.","If the data is untrusted, accept that this guard is a safety feature (prevents infinite loops) and reject the archive."],"exampleFix":"// before\ntry { await lzwDecompress(untrustedBytes, limit); } catch { /* ignore */ }\n// after\nif (!isCompressZ(untrustedBytes)) throw new Error(\"not .Z\");\ntry {\n  const out = await lzwDecompress(untrustedBytes, limit);\n} catch (e) {\n  throw new Error(`archive corrupt, refusing to decode: ${e.message}`);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await lzwDecompress(untrustedBytes, maxOutput);\n} catch (e) {\n  if (e instanceof ArchiveError && e.message.includes(\"Corrupt compress (.Z) dictionary chain\")) {\n    throw new Error(\"Refusing to decode: .Z dictionary chain is corrupt (possible malicious input)\");\n  }\n  throw e;\n}","preventionTips":["Always keep a sane maxOutput limit — never pass Infinity — when decoding untrusted archives.","Reject archives that fail checksums instead of attempting best-effort decode.","Remember this guard also protects against infinite/deep chains; do not attempt to bypass it."],"tags":["archive","lzw","corrupt-data","security"],"backgroundTag":"corrupt-compressed-data","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}