This is an automated email from the ASF dual-hosted git repository. bodewig pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push: new 32509ee COMPRESS-567 use IOException rather than RuntimeExceptions 32509ee is described below commit 32509ee94cef4d34ee6e1e82bd044331036ae273 Author: Stefan Bodewig <bode...@apache.org> AuthorDate: Sun Feb 28 11:41:58 2021 +0100 COMPRESS-567 use IOException rather than RuntimeExceptions Most of the time the parameters passed to these methods are directly read from archives or streams. Users of our classes expect IOExceptions for corrupt archives. Throwing IOException from our internal classes avoids having to perform the same type of checks and throwing inside the calling code everywhere. --- src/changes/changes.xml | 10 ++++++++++ .../org/apache/commons/compress/archivers/zip/ZipFile.java | 4 ++++ .../java/org/apache/commons/compress/utils/BitInputStream.java | 2 +- .../commons/compress/utils/FixedLengthBlockOutputStream.java | 2 +- .../compress/utils/MultiReadOnlySeekableByteChannel.java | 2 +- .../commons/compress/utils/SeekableInMemoryByteChannel.java | 4 +++- .../org/apache/commons/compress/utils/BitInputStreamTest.java | 4 ++-- .../compress/utils/MultiReadOnlySeekableByteChannelTest.java | 8 ++++---- .../compress/utils/SeekableInMemoryByteChannelTest.java | 8 ++++---- 9 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 83cfc1a..e873eb5 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -306,6 +306,16 @@ The <action> type attribute can be add,update,fix,remove. certain ZIP archives. Github Pull Request #172. </action> + <action issue="COMPRESS-567" type="fix" date="2021-02-28"> + Made some of the stream classes used internally throw + IOExceptions on illegal arguments rather than + RuntimeExceptions to make it more likely that corrupt archives + cause expected checked exceptions rather than RuntimException + for various formats. + + Fixes a specific case for ZIP but affects other formats as + well. + </action> </release> <release version="1.20" date="2020-02-08" description="Release 1.20 (Java 7)"> diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java index 8635f76..c8e366b 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java @@ -1317,6 +1317,10 @@ public class ZipFile implements Closeable { * underlying archive channel. */ private BoundedArchiveInputStream createBoundedInputStream(final long start, final long remaining) { + if (start < 0 || remaining < 0 || start + remaining < start) { + throw new IllegalArgumentException("Corrupted archive, stream boundaries" + + " are out of range"); + } return archive instanceof FileChannel ? new BoundedFileChannelInputStream(start, remaining) : new BoundedSeekableByteChannelInputStream(start, remaining, archive); diff --git a/src/main/java/org/apache/commons/compress/utils/BitInputStream.java b/src/main/java/org/apache/commons/compress/utils/BitInputStream.java index e683b50..b8001c4 100644 --- a/src/main/java/org/apache/commons/compress/utils/BitInputStream.java +++ b/src/main/java/org/apache/commons/compress/utils/BitInputStream.java @@ -80,7 +80,7 @@ public class BitInputStream implements Closeable { */ public long readBits(final int count) throws IOException { if (count < 0 || count > MAXIMUM_CACHE_SIZE) { - throw new IllegalArgumentException("count must not be negative or greater than " + MAXIMUM_CACHE_SIZE); + throw new IOException("count must not be negative or greater than " + MAXIMUM_CACHE_SIZE); } if (ensureCache(count)) { return -1; diff --git a/src/main/java/org/apache/commons/compress/utils/FixedLengthBlockOutputStream.java b/src/main/java/org/apache/commons/compress/utils/FixedLengthBlockOutputStream.java index 7320f90..1de269e 100644 --- a/src/main/java/org/apache/commons/compress/utils/FixedLengthBlockOutputStream.java +++ b/src/main/java/org/apache/commons/compress/utils/FixedLengthBlockOutputStream.java @@ -235,7 +235,7 @@ public class FixedLengthBlockOutputStream extends OutputStream implements Writab throw new ClosedChannelException(); } if (!buffer.hasArray()) { - throw new IllegalArgumentException("Direct buffer somehow written to BufferAtATimeOutputChannel"); + throw new IOException("Direct buffer somehow written to BufferAtATimeOutputChannel"); } try { diff --git a/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java b/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java index f0c166c..b2233eb 100644 --- a/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java +++ b/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java @@ -180,7 +180,7 @@ public class MultiReadOnlySeekableByteChannel implements SeekableByteChannel { @Override public synchronized SeekableByteChannel position(final long newPosition) throws IOException { if (newPosition < 0) { - throw new IllegalArgumentException("Negative position: " + newPosition); + throw new IOException("Negative position: " + newPosition); } if (!isOpen()) { throw new ClosedChannelException(); diff --git a/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java b/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java index bee0751..749e50c 100644 --- a/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java +++ b/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java @@ -91,7 +91,7 @@ public class SeekableInMemoryByteChannel implements SeekableByteChannel { public SeekableByteChannel position(final long newPosition) throws IOException { ensureOpen(); if (newPosition < 0L || newPosition > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Position has to be in range 0.. " + Integer.MAX_VALUE); + throw new IOException("Position has to be in range 0.. " + Integer.MAX_VALUE); } position = (int) newPosition; return this; @@ -113,6 +113,8 @@ public class SeekableInMemoryByteChannel implements SeekableByteChannel { * * <p>This method violates the contract of {@link SeekableByteChannel#truncate} as it will not throw any exception when * invoked on a closed channel.</p> + * + * @throws IllegalArgumentException if size is negative or bigger than the maximum of a Java integer */ @Override public SeekableByteChannel truncate(final long newSize) { diff --git a/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java b/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java index ce996b3..b1916c5 100644 --- a/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java +++ b/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java @@ -28,14 +28,14 @@ import org.junit.Test; public class BitInputStreamTest { - @Test(expected = IllegalArgumentException.class) + @Test(expected = IOException.class) public void shouldNotAllowReadingOfANegativeAmountOfBits() throws IOException { try (final BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) { bis.readBits(-1); } } - @Test(expected = IllegalArgumentException.class) + @Test(expected = IOException.class) public void shouldNotAllowReadingOfMoreThan63BitsAtATime() throws IOException { try (final BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) { bis.readBits(64); diff --git a/src/test/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannelTest.java b/src/test/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannelTest.java index 1bdfd3c..a12630e 100644 --- a/src/test/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannelTest.java +++ b/src/test/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannelTest.java @@ -139,7 +139,7 @@ public class MultiReadOnlySeekableByteChannelTest { @Test public void cantPositionToANegativePosition() throws IOException { final SeekableByteChannel s = MultiReadOnlySeekableByteChannel.forSeekableByteChannels(makeEmpty(), makeEmpty()); - thrown.expect(IllegalArgumentException.class); + thrown.expect(IOException.class); s.position(-1); } @@ -374,11 +374,11 @@ public class MultiReadOnlySeekableByteChannelTest { } /* - * <q>IllegalArgumentException - If the new position is negative</q> + * <q>IOException - If the new position is negative</q> */ @Test - public void throwsIllegalArgumentExceptionWhenPositionIsSetToANegativeValue() throws Exception { - thrown.expect(IllegalArgumentException.class); + public void throwsIOExceptionWhenPositionIsSetToANegativeValue() throws Exception { + thrown.expect(IOException.class); try (SeekableByteChannel c = testChannel()) { c.position(-1); } diff --git a/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java b/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java index f5c79f9..7eee967 100644 --- a/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java +++ b/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java @@ -184,7 +184,7 @@ public class SeekableInMemoryByteChannelTest { c.close(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = IOException.class) public void shouldThrowExceptionWhenSettingIncorrectPosition() throws IOException { //given final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(); @@ -297,10 +297,10 @@ public class SeekableInMemoryByteChannelTest { } /* - * <q>IllegalArgumentException - If the new position is negative</q> + * <q>IOException - If the new position is negative</q> */ - @Test(expected = IllegalArgumentException.class) - public void throwsIllegalArgumentExceptionWhenPositionIsSetToANegativeValue() throws Exception { + @Test(expected = IOException.class) + public void throwsIOExceptionWhenPositionIsSetToANegativeValue() throws Exception { try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) { c.position(-1); }