You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2025/08/02 18:40:11 UTC
(commons-compress) 03/03: org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream throws CompressorException (an IOException subclass) instead of IOException when it encounters formatting problems
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit e2db017bee5b38e9ed1a12d242fbe9712b567299
Author: Gary D. Gregory <ga...@gmail.com>
AuthorDate: Sat Aug 2 14:40:02 2025 -0400
org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream
throws CompressorException (an IOException subclass) instead of
IOException when it encounters formatting problems
---
src/changes/changes.xml | 3 +-
.../bzip2/BZip2CompressorInputStream.java | 51 ++++++----------------
.../bzip2/BZip2CompressorInputStreamTest.java | 6 +--
3 files changed, 19 insertions(+), 41 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d3cc5729b..0b291299b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -53,7 +53,8 @@ The <action> type attribute can be add,update,fix,remove.
<action type="fix" dev="ggregory" due-to="Tyler Nighswander, Gary Gregory">org.apache.commons.compress.archivers.sevenz.SevenZFile.Builder.get() now throws an ArchiveException instead of an IllegalArgumentException.</action>
<action type="fix" dev="ggregory" due-to="Tyler Nighswander, Gary Gregory">Fix format string in org.apache.commons.compress.archivers.sevenz.SevenZFile.assertFitsIntoNonNegativeInt(String, long).</action>
<action type="fix" dev="ggregory" due-to="Tyler Nighswander, Gary Gregory">org.apache.commons.compress.archivers.sevenz.SevenZFile.Builder.get() now throws an ArchiveException instead of an OOME.</action>
- <action type="fix" dev="ggregory" due-to="Tyler Nighswander, Gary Gregory">org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream constructors now throws ArchiveException instead of ArrayIndexOutOfBoundsException.</action>
+ <action type="fix" dev="ggregory" due-to="Tyler Nighswander, Gary Gregory">org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream constructors now throws CompressorException instead of ArrayIndexOutOfBoundsException.</action>
+ <action type="fix" dev="ggregory" due-to="Gary Gregory">org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream throws CompressorException (an IOException subclass) instead of IOException when it encounters formatting problems.</action>
<!-- ADD -->
<!-- UPDATE -->
</release>
diff --git a/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java
index 380937035..49debbe34 100644
--- a/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java
@@ -139,7 +139,7 @@ private static char bsGetUByte(final BitInputStream bin) throws IOException {
private static int bsR(final BitInputStream bin, final int n) throws IOException {
final long thech = bin.readBits(n);
if (thech < 0) {
- throw new IOException("Unexpected end of stream");
+ throw new CompressorException("Unexpected end of stream");
}
return (int) thech;
}
@@ -288,7 +288,7 @@ private boolean complete() throws IOException {
this.currentState = EOF;
this.data = null;
if (this.storedCombinedCRC != this.computedCombinedCRC) {
- throw new IOException("BZip2 CRC error");
+ throw new CompressorException("BZip2 CRC error");
}
// Look for the next .bz2 stream if decompressing
// concatenated files.
@@ -332,7 +332,7 @@ private void endBlock() throws IOException {
// (repair feature, not yet documented, not tested)
this.computedCombinedCRC = this.storedCombinedCRC << 1 | this.storedCombinedCRC >>> 31;
this.computedCombinedCRC ^= this.storedBlockCRC;
- throw new IOException("BZip2 CRC error");
+ throw new CompressorException("BZip2 CRC error");
}
this.computedCombinedCRC = this.computedCombinedCRC << 1 | this.computedCombinedCRC >>> 31;
this.computedCombinedCRC ^= computedBlockCRC;
@@ -353,7 +353,6 @@ private void getAndMoveToFrontDecode() throws IOException {
final int[][] base = dataShadow.base;
final int[][] perm = dataShadow.perm;
final int limitLast = this.blockSize100k * 100000;
-
/*
* Setting up the unzftab entries here is not strictly necessary, but it does save having to do it later in a separate pass, and so saves a block's
* worth of cache misses.
@@ -362,7 +361,6 @@ private void getAndMoveToFrontDecode() throws IOException {
yy[i] = (char) i;
unzftab[i] = 0;
}
-
int groupNo = 0;
int groupPos = G_SIZE - 1;
final int eob = this.nInUse + 1;
@@ -374,11 +372,9 @@ private void getAndMoveToFrontDecode() throws IOException {
int[] limit_zt = limit[zt];
int[] perm_zt = perm[zt];
int minLens_zt = minLens[zt];
-
while (nextSym != eob) {
if (nextSym == RUNA || nextSym == RUNB) {
int s = -1;
-
for (int n = 1; true; n <<= 1) {
if (nextSym == RUNA) {
s += n;
@@ -387,7 +383,6 @@ private void getAndMoveToFrontDecode() throws IOException {
} else {
break;
}
-
if (groupPos == 0) {
groupPos = G_SIZE - 1;
checkBounds(++groupNo, MAX_SELECTORS, "groupNo");
@@ -400,7 +395,6 @@ private void getAndMoveToFrontDecode() throws IOException {
} else {
groupPos--;
}
-
int zn = minLens_zt;
checkBounds(zn, MAX_ALPHA_SIZE, "zn");
int zvec = bsR(bin, zn);
@@ -413,31 +407,26 @@ private void getAndMoveToFrontDecode() throws IOException {
nextSym = perm_zt[tmp];
}
checkBounds(s, this.data.ll8.length, "s");
-
final int yy0 = yy[0];
checkBounds(yy0, 256, "yy");
final byte ch = seqToUnseq[yy0];
unzftab[ch & 0xff] += s + 1;
-
final int from = ++lastShadow;
lastShadow += s;
checkBounds(lastShadow, this.data.ll8.length, "lastShadow");
Arrays.fill(ll8, from, lastShadow + 1, ch);
-
if (lastShadow >= limitLast) {
- throw new IOException("Block overrun while expanding RLE in MTF, " + lastShadow + " exceeds " + limitLast);
+ throw new CompressorException("Block overrun while expanding RLE in MTF, " + lastShadow + " exceeds " + limitLast);
}
} else {
if (++lastShadow >= limitLast) {
- throw new IOException("Block overrun in MTF, " + lastShadow + " exceeds " + limitLast);
+ throw new CompressorException("Block overrun in MTF, " + lastShadow + " exceeds " + limitLast);
}
checkBounds(nextSym, 256 + 1, "nextSym");
-
final char tmp = yy[nextSym - 1];
checkBounds(tmp, 256, "yy");
unzftab[seqToUnseq[tmp] & 0xff]++;
ll8[lastShadow] = seqToUnseq[tmp];
-
/*
* This loop is hammered during decompression, hence avoid native method call overhead of System.arraycopy for very small ranges to copy.
*/
@@ -448,9 +437,7 @@ private void getAndMoveToFrontDecode() throws IOException {
} else {
System.arraycopy(yy, 0, yy, 1, nextSym - 1);
}
-
yy[0] = tmp;
-
if (groupPos == 0) {
groupPos = G_SIZE - 1;
checkBounds(++groupNo, MAX_SELECTORS, "groupNo");
@@ -463,7 +450,6 @@ private void getAndMoveToFrontDecode() throws IOException {
} else {
groupPos--;
}
-
int zn = minLens_zt;
checkBounds(zn, MAX_ALPHA_SIZE, "zn");
int zvec = bsR(bin, zn);
@@ -476,7 +462,6 @@ private void getAndMoveToFrontDecode() throws IOException {
nextSym = perm_zt[idx];
}
}
-
this.last = lastShadow;
}
@@ -494,7 +479,6 @@ private int getAndMoveToFrontDecode0() throws IOException {
}
final int tmp = zvec - dataShadow.base[zt][zn];
checkBounds(tmp, MAX_ALPHA_SIZE, "zvec");
-
return dataShadow.perm[zt][tmp];
}
@@ -507,34 +491,27 @@ public long getCompressedCount() {
}
private boolean init(final boolean isFirstStream) throws IOException {
- if (null == bin) {
- throw new IOException("No InputStream");
+ if (bin == null) {
+ throw new CompressorException("No InputStream");
}
-
if (!isFirstStream) {
bin.clearBitCache();
}
-
final int magic0 = readNextByte(this.bin);
if (magic0 == -1 && !isFirstStream) {
return false;
}
final int magic1 = readNextByte(this.bin);
final int magic2 = readNextByte(this.bin);
-
if (magic0 != 'B' || magic1 != 'Z' || magic2 != 'h') {
- throw new IOException(isFirstStream ? "Stream is not in the BZip2 format" : "Unexpected data after a valid BZip2 stream");
+ throw new CompressorException(isFirstStream ? "Stream is not in the BZip2 format" : "Unexpected data after a valid BZip2 stream");
}
-
final int blockSize = readNextByte(this.bin);
if (blockSize < '1' || blockSize > '9') {
- throw new IOException("BZip2 block size is invalid");
+ throw new CompressorException("BZip2 block size is invalid");
}
-
this.blockSize100k = blockSize - '0';
-
this.computedCombinedCRC = 0;
-
return true;
}
@@ -577,7 +554,7 @@ private void initBlock() throws IOException {
magic5 != 0x59 // 'Y'
) {
this.currentState = EOF;
- throw new IOException("Bad block header");
+ throw new CompressorException("Bad block header");
}
this.storedBlockCRC = bsGetInt(bin);
this.blockRandomised = bsR(bin, 1) == 1;
@@ -618,7 +595,7 @@ public int read() throws IOException {
count(r < 0 ? -1 : 1);
return r;
}
- throw new IOException("Stream closed");
+ throw new CompressorException("Stream closed");
}
/*
@@ -638,7 +615,7 @@ public int read(final byte[] dest, final int offs, final int len) throws IOExcep
throw new IndexOutOfBoundsException("offs(" + offs + ") + len(" + len + ") > dest.length(" + dest.length + ").");
}
if (this.bin == null) {
- throw new IOException("Stream closed");
+ throw new CompressorException("Stream closed");
}
if (len == 0) {
return 0;
@@ -726,7 +703,7 @@ private void recvDecodingTables() throws IOException {
final int nGroups = bsR(bin, 3);
final int selectors = bsR(bin, 15);
if (selectors < 0) {
- throw new IOException("Corrupted input, nSelectors value negative");
+ throw new CompressorException("Corrupted input, nSelectors value negative");
}
checkBounds(alphaSize, MAX_ALPHA_SIZE + 1, "alphaSize");
checkBounds(nGroups, N_GROUPS + 1, "nGroups");
@@ -806,7 +783,7 @@ private int setupBlock() throws IOException {
}
if (this.origPtr < 0 || this.origPtr >= tt.length) {
- throw new IOException("Stream corrupted");
+ throw new CompressorException("Stream corrupted");
}
this.su_tPos = tt[this.origPtr];
diff --git a/src/test/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStreamTest.java b/src/test/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStreamTest.java
index 768540974..778832668 100644
--- a/src/test/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStreamTest.java
@@ -104,7 +104,7 @@ void testReadOfLength0ShouldReturn0() throws Exception {
@Test
void testShouldThrowAnIOExceptionWhenAppliedToAZipFile() throws Exception {
try (InputStream in = newInputStream("bla.zip")) {
- assertThrows(IOException.class, () -> new BZip2CompressorInputStream(in));
+ assertThrows(CompressorException.class, () -> new BZip2CompressorInputStream(in));
}
}
@@ -115,7 +115,7 @@ void testShouldThrowAnIOExceptionWhenAppliedToAZipFile() throws Exception {
*/
@Test
void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS516() {
- assertThrows(IOException.class,
+ assertThrows(CompressorException.class,
() -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x2e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0xb6, 0xfe, 0x77, 0x63,
0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x09, 0x00, 0x03, 0xe7, 0xce, 0x64,
0x55, 0xf3, 0xce, 0x64, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x42, 0x5a,
@@ -130,7 +130,7 @@ void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS516() {
*/
@Test
void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS519() {
- assertThrows(IOException.class,
+ assertThrows(CompressorException.class,
() -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x2e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0xb6, 0xfe, 0x77, 0x63,
0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x09, 0x00, 0x03, 0xe7, 0xce, 0x64,
0x55, 0xf3, 0xce, 0x64, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x42, 0x5a,