MuntashirAkon/AppManager · error · IOException
Stream corrupted
Error message
Stream corrupted
What it means
After building the inverse-BWT 'tt' table, the decoder validates origPtr (the starting pointer stored in the block header) against the table bounds. If origPtr is negative or beyond tt.length, the block header is inconsistent with the decoded data — the stream is corrupt and cannot be inverted.
Source
Thrown at app/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java:755
final int ttLen = this.last + 1;
final int[] tt = this.data.initTT(ttLen);
final byte[] ll8 = this.data.ll8;
cftab[0] = 0;
System.arraycopy(this.data.unzftab, 0, cftab, 1, 256);
for (int i = 1, c = cftab[0]; i <= 256; i++) {
c += cftab[i];
cftab[i] = c;
}
for (int i = 0, lastShadow = this.last; i <= lastShadow; i++) {
final int tmp = cftab[ll8[i] & 0xff]++;
checkBounds(tmp, ttLen, "tt index");
tt[tmp] = i;
}
if ((this.origPtr < 0) || (this.origPtr >= tt.length)) {
throw new IOException("Stream corrupted");
}
this.su_tPos = tt[this.origPtr];
this.su_count = 0;
this.su_i2 = 0;
this.su_ch2 = 256; /* not a char and not EOF */
if (this.blockRandomised) {
this.su_rNToGo = 0;
this.su_rTPos = 0;
return setupRandPartA();
}
return setupNoRandPartA();
}
private int setupRandPartA() throws IOException {
if (this.su_i2 <= this.last) {
this.su_chPrev = this.su_ch2;View on GitHub (pinned to 0152f468fc)
Solutions
- Validate the source with `bzip2 -t` and replace the corrupt file.
- Confirm you decompress the complete stream from byte 0 (no offsets/resume).
- Catch IOException and convert to a domain-specific 'corrupt archive' error for callers.
- Keep commons-compress updated — these checks are additions from hardening fixes; older versions may crash instead.
Example fix
// before
new BZip2CompressorInputStream(raw); // may throw 'Stream corrupted' mid-read
// after
try (BZip2CompressorInputStream bz = new BZip2CompressorInputStream(raw)) {
// read
} catch (IOException e) {
throw new CorruptArchiveException("invalid bzip2 stream: " + e.getMessage(), e);
} Defensive patterns
Strategy: try-catch
Try / catch
try (BZip2CompressorInputStream bz = new BZip2CompressorInputStream(raw)) {
// read
} catch (IOException e) {
if ("Stream corrupted".equals(e.getMessage()))
throw new CorruptArchiveException("bad origPtr / corrupt block", e);
throw e;
} Prevention
- Use the latest commons-compress (pre-hardening versions could misbehave on such input)
- Verify archive integrity before decompression
- Isolate untrusted decompression in a guarded step (limits + catch)
- Never treat decoded output as valid if any IOException occurred
When it happens
Trigger: BZip2CompressorInputStream.read() during final BWT inversion in setupBlock/getAndMoveToFrontDecode: origPtr from the block header falls outside tt.length.
Common situations: Corrupted block headers from truncated/flipped-bit files, crafted malicious archives, feeding non-bzip2 bytes to the decompressor.
Related errors
- Corrupted input, " + name + " value negative
- Corrupted input, " + name + " value too big
- Corrupted input, nSelectors value negative
- Block overrun while expanding RLE in MTF, " + lastShadow + "
- Block overrun in MTF, " + lastShadow + " exceeds " + limitLa
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/4aca4a80ad51a6bd.
Report an issue: GitHub.