{"record":{"id":"29506fc882ceb355","repo":"MuntashirAkon/AppManager","slug":"block-overrun-in-mtf-lastshadow-exceeds-limitlast","errorCode":null,"errorMessage":"Block overrun in MTF, \" + lastShadow + \" exceeds \" + limitLast","messagePattern":"Block overrun in MTF, \" \\+ lastShadow \\+ \" exceeds \" \\+ limitLast","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java","lineNumber":659,"sourceCode":"                checkBounds(s, this.data.ll8.length, \"s\");\n\n                final int yy0 = yy[0];\n                checkBounds(yy0, 256, \"yy\");\n                final byte ch = seqToUnseq[yy0];\n                unzftab[ch & 0xff] += s + 1;\n\n                final int from = ++lastShadow;\n                lastShadow += s;\n                checkBounds(lastShadow, this.data.ll8.length, \"lastShadow\");\n                Arrays.fill(ll8, from, lastShadow + 1, ch);\n\n                if (lastShadow >= limitLast) {\n                    throw new IOException(\"Block overrun while expanding RLE in MTF, \"\n                            + lastShadow + \" exceeds \" + limitLast);\n                }\n            } else {\n                if (++lastShadow >= limitLast) {\n                    throw new IOException(\"Block overrun in MTF, \"\n                            + lastShadow + \" exceeds \" + limitLast);\n                }\n                checkBounds(nextSym, 256 + 1, \"nextSym\");\n\n                final char tmp = yy[nextSym - 1];\n                checkBounds(tmp, 256, \"yy\");\n                unzftab[seqToUnseq[tmp] & 0xff]++;\n                ll8[lastShadow] = seqToUnseq[tmp];\n\n                /*\n                 * This loop is hammered during decompression, hence avoid\n                 * native method call overhead of System.arraycopy for very\n                 * small ranges to copy.\n                 */\n                if (nextSym <= 16) {\n                    for (int j = nextSym - 1; j > 0;) {\n                        yy[j] = yy[--j];\n                    }","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java#L641-L677","documentation":"In the MTF (move-to-front) decoding stage, a plain symbol increments lastShadow; if it reaches or exceeds limitLast the block produced more output than its declared size, indicating corruption. This guard prevents writing past the block's bounds.","triggerScenarios":"BZip2CompressorInputStream.read() while decoding a bzip2 block: an MTF symbol increments lastShadow to >= limitLast.","commonSituations":"Bit-corrupted .bz2 files, truncated transfers, hostile/fuzzed inputs, wrong decoder fed non-bzip2 bytes.","solutions":["Re-verify/re-download the archive; the data is corrupt.","Don't reuse or resume partially read streams; decompress from the beginning.","Catch IOException and handle as 'corrupt input', not as a library bug.","Constrain decompressed output size for untrusted inputs (decompression-bomb defense)."],"exampleFix":"// before\nreadAll(bz); // crashes with raw IOException\n// after\ntry { readAll(bz); }\ncatch (IOException e) { log.warn(\"Corrupt bzip2 member skipped: \" + e.getMessage()); }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { readAll(bz); }\ncatch (IOException e) {\n    log.warn(\"Skipping corrupt bzip2 member: {}\", e.getMessage());\n}","preventionTips":["Decompress from byte 0; never reuse partially-consumed streams","Detect truncation before reading (compare file size/checksum)","Apply output-size limits for hostile inputs","Fail fast: don't write partially decoded output to final storage"],"tags":["io","bzip2","corrupt-input","mtf"],"backgroundTag":"corrupt-input-data","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}