You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2019/08/08 16:29:46 UTC
[commons-compress] branch master updated: COMPRESS-490 throw
IOException for certain malformed archives
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 5836405 COMPRESS-490 throw IOException for certain malformed archives
5836405 is described below
commit 58364058bd2903ebd1568f6df22161e142a0dc86
Author: Stefan Bodewig <bo...@apache.org>
AuthorDate: Thu Aug 8 18:28:41 2019 +0200
COMPRESS-490 throw IOException for certain malformed archives
---
src/changes/changes.xml | 4 +++
.../lz4/BlockLZ4CompressorInputStream.java | 12 ++++++++-
.../AbstractLZ77CompressorInputStream.java | 28 ++++++++++++++++++-
.../snappy/SnappyCompressorInputStream.java | 31 +++++++++++++++++++---
4 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index cd51c61..b41a411 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -92,6 +92,10 @@ The <action> type attribute can be add,update,fix,remove.
gathered output in the same order they have been added.
Github Pull Requests #78 and #79.
</action>
+ <action type="fix" date="2019-08-08" issue="COMPRESS-490">
+ Throw IOException rather than RuntimeExceptions for certain
+ malformed LZ4 or Snappy inputs.
+ </action>
</release>
<release version="1.18" date="2018-08-16"
description="Release 1.18">
diff --git a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java
index a52dc60..493ec4e 100644
--- a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java
@@ -100,6 +100,9 @@ public class BlockLZ4CompressorInputStream extends AbstractLZ77CompressorInputSt
if (literalSizePart == BACK_REFERENCE_SIZE_MASK) {
literalSizePart += readSizeBytes();
}
+ if (literalSizePart < 0) {
+ throw new IOException("illegal block with a negative literal size found");
+ }
startLiteral(literalSizePart);
state = State.IN_LITERAL;
}
@@ -136,7 +139,14 @@ public class BlockLZ4CompressorInputStream extends AbstractLZ77CompressorInputSt
backReferenceSize += readSizeBytes();
}
// minimal match length 4 is encoded as 0
- startBackReference(backReferenceOffset, backReferenceSize + 4);
+ if (backReferenceSize < 0) {
+ throw new IOException("illegal block with a negative match length found");
+ }
+ try {
+ startBackReference(backReferenceOffset, backReferenceSize + 4);
+ } catch (IllegalArgumentException ex) {
+ throw new IOException("illegal block with bad offset found", ex);
+ }
state = State.IN_BACK_REFERENCE;
return true;
}
diff --git a/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java
index 31196ef..ed0cb3c 100644
--- a/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java
@@ -130,9 +130,13 @@ public abstract class AbstractLZ77CompressorInputStream extends CompressorInputS
* Size of the window kept for back-references, must be bigger than the biggest offset expected.
*
* @throws IOException if reading fails
+ * @throws IllegalArgumentException if windowSize is not bigger than 0
*/
public AbstractLZ77CompressorInputStream(final InputStream is, int windowSize) throws IOException {
this.in = new CountingInputStream(is);
+ if (windowSize <= 0) {
+ throw new IllegalArgumentException("windowSize must be bigger than 0");
+ }
this.windowSize = windowSize;
buf = new byte[3 * windowSize];
writeIndex = readIndex = 0;
@@ -201,8 +205,12 @@ public abstract class AbstractLZ77CompressorInputStream extends CompressorInputS
* Used by subclasses to signal the next block contains the given
* amount of literal data.
* @param length the length of the block
+ * @throws IllegalArgumentException if length is negative
*/
protected final void startLiteral(long length) {
+ if (length < 0) {
+ throw new IllegalArgumentException("length must not be negative");
+ }
bytesRemaining = length;
}
@@ -224,6 +232,10 @@ public abstract class AbstractLZ77CompressorInputStream extends CompressorInputS
* @throws IOException if the underlying stream throws or signals
* an EOF before the amount of data promised for the block have
* been read
+ * @throws NullPointerException if <code>b</code> is null
+ * @throws IndexOutOfBoundsException if <code>off</code> is
+ * negative, <code>len</code> is negative, or <code>len</code> is
+ * greater than <code>b.length - off</code>
*/
protected final int readLiteral(final byte[] b, final int off, final int len) throws IOException {
final int avail = available();
@@ -234,7 +246,7 @@ public abstract class AbstractLZ77CompressorInputStream extends CompressorInputS
}
private void tryToReadLiteral(int bytesToRead) throws IOException {
- // min of "what is still inside the literal", "what does the user want" and "how muc can fit into the buffer"
+ // min of "what is still inside the literal", "what does the user want" and "how much can fit into the buffer"
final int reallyTryToRead = Math.min((int) Math.min(bytesToRead, bytesRemaining),
buf.length - writeIndex);
final int bytesRead = reallyTryToRead > 0
@@ -271,8 +283,18 @@ public abstract class AbstractLZ77CompressorInputStream extends CompressorInputS
* Used by subclasses to signal the next block contains a back-reference with the given coordinates.
* @param offset the offset of the back-reference
* @param length the length of the back-reference
+ * @throws IllegalArgumentException if offset not bigger than 0 or
+ * bigger than the number of bytes available for back-references
+ * or if length is negative
*/
protected final void startBackReference(int offset, long length) {
+ if (offset <= 0 || offset > writeIndex) {
+ throw new IllegalArgumentException("offset must be bigger than 0 but not bigger than the number"
+ + " of bytes available for back-references");
+ }
+ if (length < 0) {
+ throw new IllegalArgumentException("length must not be negative");
+ }
backReferenceOffset = offset;
bytesRemaining = length;
}
@@ -284,6 +306,10 @@ public abstract class AbstractLZ77CompressorInputStream extends CompressorInputS
* @param len maximum amount of data to read
* @return number of bytes read, may be 0. Will never return -1 as
* EOF-detection is the responsibility of the subclass
+ * @throws NullPointerException if <code>b</code> is null
+ * @throws IndexOutOfBoundsException if <code>off</code> is
+ * negative, <code>len</code> is negative, or <code>len</code> is
+ * greater than <code>b.length - off</code>
*/
protected final int readBackReference(final byte[] b, final int off, final int len) {
final int avail = available();
diff --git a/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java
index 4650cb8..4657ac8 100644
--- a/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java
@@ -78,6 +78,7 @@ public class SnappyCompressorInputStream extends AbstractLZ77CompressorInputStre
* The block size used in compression
*
* @throws IOException if reading fails
+ * @throws IllegalArgumentException if blockSize is not bigger than 0
*/
public SnappyCompressorInputStream(final InputStream is, final int blockSize)
throws IOException {
@@ -135,6 +136,9 @@ public class SnappyCompressorInputStream extends AbstractLZ77CompressorInputStre
case 0x00:
length = readLiteralLength(b);
+ if (length < 0) {
+ throw new IOException("illegal block with a negative literal size found");
+ }
uncompressedBytesRemaining -= length;
startLiteral(length);
state = State.IN_LITERAL;
@@ -152,6 +156,9 @@ public class SnappyCompressorInputStream extends AbstractLZ77CompressorInputStre
*/
length = 4 + ((b >> 2) & 0x07);
+ if (length < 0) {
+ throw new IOException("illegal block with a negative match length found");
+ }
uncompressedBytesRemaining -= length;
offset = (b & 0xE0) << 3;
b = readOneByte();
@@ -160,7 +167,11 @@ public class SnappyCompressorInputStream extends AbstractLZ77CompressorInputStre
}
offset |= b;
- startBackReference(offset, length);
+ try {
+ startBackReference(offset, length);
+ } catch (IllegalArgumentException ex) {
+ throw new IOException("illegal block with bad offset found", ex);
+ }
state = State.IN_BACK_REFERENCE;
break;
@@ -175,11 +186,18 @@ public class SnappyCompressorInputStream extends AbstractLZ77CompressorInputStre
*/
length = (b >> 2) + 1;
+ if (length < 0) {
+ throw new IOException("illegal block with a negative match length found");
+ }
uncompressedBytesRemaining -= length;
offset = (int) ByteUtils.fromLittleEndian(supplier, 2);
- startBackReference(offset, length);
+ try {
+ startBackReference(offset, length);
+ } catch (IllegalArgumentException ex) {
+ throw new IOException("illegal block with bad offset found", ex);
+ }
state = State.IN_BACK_REFERENCE;
break;
@@ -193,11 +211,18 @@ public class SnappyCompressorInputStream extends AbstractLZ77CompressorInputStre
*/
length = (b >> 2) + 1;
+ if (length < 0) {
+ throw new IOException("illegal block with a negative match length found");
+ }
uncompressedBytesRemaining -= length;
offset = (int) ByteUtils.fromLittleEndian(supplier, 4) & 0x7fffffff;
- startBackReference(offset, length);
+ try {
+ startBackReference(offset, length);
+ } catch (IllegalArgumentException ex) {
+ throw new IOException("illegal block with bad offset found", ex);
+ }
state = State.IN_BACK_REFERENCE;
break;
default:
Re: [commons-compress] branch master updated: COMPRESS-490 throw
IOException for certain malformed archives
Posted by Gary Gregory <ga...@gmail.com>.
IMO exceptions messages should start with a capital letter, like a
sentence.
Gary
On Thu, Aug 8, 2019, 12:29 <bo...@apache.org> wrote:
> 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 5836405 COMPRESS-490 throw IOException for certain malformed
> archives
> 5836405 is described below
>
> commit 58364058bd2903ebd1568f6df22161e142a0dc86
> Author: Stefan Bodewig <bo...@apache.org>
> AuthorDate: Thu Aug 8 18:28:41 2019 +0200
>
> COMPRESS-490 throw IOException for certain malformed archives
> ---
> src/changes/changes.xml | 4 +++
> .../lz4/BlockLZ4CompressorInputStream.java | 12 ++++++++-
> .../AbstractLZ77CompressorInputStream.java | 28
> ++++++++++++++++++-
> .../snappy/SnappyCompressorInputStream.java | 31
> +++++++++++++++++++---
> 4 files changed, 70 insertions(+), 5 deletions(-)
>
> diff --git a/src/changes/changes.xml b/src/changes/changes.xml
> index cd51c61..b41a411 100644
> --- a/src/changes/changes.xml
> +++ b/src/changes/changes.xml
> @@ -92,6 +92,10 @@ The <action> type attribute can be
> add,update,fix,remove.
> gathered output in the same order they have been added.
> Github Pull Requests #78 and #79.
> </action>
> + <action type="fix" date="2019-08-08" issue="COMPRESS-490">
> + Throw IOException rather than RuntimeExceptions for certain
> + malformed LZ4 or Snappy inputs.
> + </action>
> </release>
> <release version="1.18" date="2018-08-16"
> description="Release 1.18">
> diff --git
> a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java
> b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java
> index a52dc60..493ec4e 100644
> ---
> a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java
> +++
> b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorInputStream.java
> @@ -100,6 +100,9 @@ public class BlockLZ4CompressorInputStream extends
> AbstractLZ77CompressorInputSt
> if (literalSizePart == BACK_REFERENCE_SIZE_MASK) {
> literalSizePart += readSizeBytes();
> }
> + if (literalSizePart < 0) {
> + throw new IOException("illegal block with a negative literal
> size found");
> + }
> startLiteral(literalSizePart);
> state = State.IN_LITERAL;
> }
> @@ -136,7 +139,14 @@ public class BlockLZ4CompressorInputStream extends
> AbstractLZ77CompressorInputSt
> backReferenceSize += readSizeBytes();
> }
> // minimal match length 4 is encoded as 0
> - startBackReference(backReferenceOffset, backReferenceSize + 4);
> + if (backReferenceSize < 0) {
> + throw new IOException("illegal block with a negative match
> length found");
> + }
> + try {
> + startBackReference(backReferenceOffset, backReferenceSize +
> 4);
> + } catch (IllegalArgumentException ex) {
> + throw new IOException("illegal block with bad offset found",
> ex);
> + }
> state = State.IN_BACK_REFERENCE;
> return true;
> }
> diff --git
> a/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java
> b/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java
> index 31196ef..ed0cb3c 100644
> ---
> a/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java
> +++
> b/src/main/java/org/apache/commons/compress/compressors/lz77support/AbstractLZ77CompressorInputStream.java
> @@ -130,9 +130,13 @@ public abstract class
> AbstractLZ77CompressorInputStream extends CompressorInputS
> * Size of the window kept for back-references, must be
> bigger than the biggest offset expected.
> *
> * @throws IOException if reading fails
> + * @throws IllegalArgumentException if windowSize is not bigger than 0
> */
> public AbstractLZ77CompressorInputStream(final InputStream is, int
> windowSize) throws IOException {
> this.in = new CountingInputStream(is);
> + if (windowSize <= 0) {
> + throw new IllegalArgumentException("windowSize must be bigger
> than 0");
> + }
> this.windowSize = windowSize;
> buf = new byte[3 * windowSize];
> writeIndex = readIndex = 0;
> @@ -201,8 +205,12 @@ public abstract class
> AbstractLZ77CompressorInputStream extends CompressorInputS
> * Used by subclasses to signal the next block contains the given
> * amount of literal data.
> * @param length the length of the block
> + * @throws IllegalArgumentException if length is negative
> */
> protected final void startLiteral(long length) {
> + if (length < 0) {
> + throw new IllegalArgumentException("length must not be
> negative");
> + }
> bytesRemaining = length;
> }
>
> @@ -224,6 +232,10 @@ public abstract class
> AbstractLZ77CompressorInputStream extends CompressorInputS
> * @throws IOException if the underlying stream throws or signals
> * an EOF before the amount of data promised for the block have
> * been read
> + * @throws NullPointerException if <code>b</code> is null
> + * @throws IndexOutOfBoundsException if <code>off</code> is
> + * negative, <code>len</code> is negative, or <code>len</code> is
> + * greater than <code>b.length - off</code>
> */
> protected final int readLiteral(final byte[] b, final int off, final
> int len) throws IOException {
> final int avail = available();
> @@ -234,7 +246,7 @@ public abstract class
> AbstractLZ77CompressorInputStream extends CompressorInputS
> }
>
> private void tryToReadLiteral(int bytesToRead) throws IOException {
> - // min of "what is still inside the literal", "what does the user
> want" and "how muc can fit into the buffer"
> + // min of "what is still inside the literal", "what does the user
> want" and "how much can fit into the buffer"
> final int reallyTryToRead = Math.min((int) Math.min(bytesToRead,
> bytesRemaining),
> buf.length - writeIndex);
> final int bytesRead = reallyTryToRead > 0
> @@ -271,8 +283,18 @@ public abstract class
> AbstractLZ77CompressorInputStream extends CompressorInputS
> * Used by subclasses to signal the next block contains a
> back-reference with the given coordinates.
> * @param offset the offset of the back-reference
> * @param length the length of the back-reference
> + * @throws IllegalArgumentException if offset not bigger than 0 or
> + * bigger than the number of bytes available for back-references
> + * or if length is negative
> */
> protected final void startBackReference(int offset, long length) {
> + if (offset <= 0 || offset > writeIndex) {
> + throw new IllegalArgumentException("offset must be bigger
> than 0 but not bigger than the number"
> + + " of bytes available for back-references");
> + }
> + if (length < 0) {
> + throw new IllegalArgumentException("length must not be
> negative");
> + }
> backReferenceOffset = offset;
> bytesRemaining = length;
> }
> @@ -284,6 +306,10 @@ public abstract class
> AbstractLZ77CompressorInputStream extends CompressorInputS
> * @param len maximum amount of data to read
> * @return number of bytes read, may be 0. Will never return -1 as
> * EOF-detection is the responsibility of the subclass
> + * @throws NullPointerException if <code>b</code> is null
> + * @throws IndexOutOfBoundsException if <code>off</code> is
> + * negative, <code>len</code> is negative, or <code>len</code> is
> + * greater than <code>b.length - off</code>
> */
> protected final int readBackReference(final byte[] b, final int off,
> final int len) {
> final int avail = available();
> diff --git
> a/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java
> b/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java
> index 4650cb8..4657ac8 100644
> ---
> a/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java
> +++
> b/src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java
> @@ -78,6 +78,7 @@ public class SnappyCompressorInputStream extends
> AbstractLZ77CompressorInputStre
> * The block size used in compression
> *
> * @throws IOException if reading fails
> + * @throws IllegalArgumentException if blockSize is not bigger than 0
> */
> public SnappyCompressorInputStream(final InputStream is, final int
> blockSize)
> throws IOException {
> @@ -135,6 +136,9 @@ public class SnappyCompressorInputStream extends
> AbstractLZ77CompressorInputStre
> case 0x00:
>
> length = readLiteralLength(b);
> + if (length < 0) {
> + throw new IOException("illegal block with a negative
> literal size found");
> + }
> uncompressedBytesRemaining -= length;
> startLiteral(length);
> state = State.IN_LITERAL;
> @@ -152,6 +156,9 @@ public class SnappyCompressorInputStream extends
> AbstractLZ77CompressorInputStre
> */
>
> length = 4 + ((b >> 2) & 0x07);
> + if (length < 0) {
> + throw new IOException("illegal block with a negative
> match length found");
> + }
> uncompressedBytesRemaining -= length;
> offset = (b & 0xE0) << 3;
> b = readOneByte();
> @@ -160,7 +167,11 @@ public class SnappyCompressorInputStream extends
> AbstractLZ77CompressorInputStre
> }
> offset |= b;
>
> - startBackReference(offset, length);
> + try {
> + startBackReference(offset, length);
> + } catch (IllegalArgumentException ex) {
> + throw new IOException("illegal block with bad offset
> found", ex);
> + }
> state = State.IN_BACK_REFERENCE;
> break;
>
> @@ -175,11 +186,18 @@ public class SnappyCompressorInputStream extends
> AbstractLZ77CompressorInputStre
> */
>
> length = (b >> 2) + 1;
> + if (length < 0) {
> + throw new IOException("illegal block with a negative
> match length found");
> + }
> uncompressedBytesRemaining -= length;
>
> offset = (int) ByteUtils.fromLittleEndian(supplier, 2);
>
> - startBackReference(offset, length);
> + try {
> + startBackReference(offset, length);
> + } catch (IllegalArgumentException ex) {
> + throw new IOException("illegal block with bad offset
> found", ex);
> + }
> state = State.IN_BACK_REFERENCE;
> break;
>
> @@ -193,11 +211,18 @@ public class SnappyCompressorInputStream extends
> AbstractLZ77CompressorInputStre
> */
>
> length = (b >> 2) + 1;
> + if (length < 0) {
> + throw new IOException("illegal block with a negative
> match length found");
> + }
> uncompressedBytesRemaining -= length;
>
> offset = (int) ByteUtils.fromLittleEndian(supplier, 4) &
> 0x7fffffff;
>
> - startBackReference(offset, length);
> + try {
> + startBackReference(offset, length);
> + } catch (IllegalArgumentException ex) {
> + throw new IOException("illegal block with bad offset
> found", ex);
> + }
> state = State.IN_BACK_REFERENCE;
> break;
> default:
>
>