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,