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
The following commit(s) were added to refs/heads/master by this push:
new e0f21a499 [COMPRESS-632] LZWInputStream.initializeTables(int) should
throw IllegalArgumentException instead of ArrayIndexOutOfBoundsException #435
e0f21a499 is described below
commit e0f21a4996738e0275db0d6ba38cf51b07a711a0
Author: Gary Gregory <[email protected]>
AuthorDate: Fri Nov 10 08:47:28 2023 -0500
[COMPRESS-632] LZWInputStream.initializeTables(int) should throw
IllegalArgumentException instead of ArrayIndexOutOfBoundsException #435
Apply a different version of PR #435 from Yakov Shafranovich
---
src/changes/changes.xml | 1 +
.../compress/compressors/lzw/LZWInputStream.java | 10 ++++---
.../compressors/z/ZCompressorInputStreamTest.java | 34 ++++++++++++++++++++--
3 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 6448265ed..412805e02 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -86,6 +86,7 @@ The <action> type attribute can be add,update,fix,remove.
<action type="fix" dev="ggregory" due-to="Gary Gregory">Use the root
Locale for string conversion of command line options in
org.apache.commons.compress.archivers.sevenz.CLI.</action>
<action type="fix" dev="ggregory" due-to="Gary Gregory">Calling
PackingUtils.config(PackingOptions) with null now closes the internal
FileHandler.</action>
<action type="fix" issue="COMPRESS-650" dev="ggregory" due-to="Chad
Preisler">LZ4 compressor throws IndexOutOfBoundsException.</action>
+ <action type="fix" issue="COMPRESS-632" dev="ggregory" due-to="Yakov
Shafranovich, Gary Gregory">LZWInputStream.initializeTables(int) should throw
IllegalArgumentException instead of ArrayIndexOutOfBoundsException.</action>
<!-- UPDATE -->
<action type="update" dev="ggregory" due-to="Dependabot">Bump
org.slf4j:slf4j-api from 2.0.8 to 2.0.9 #413.</action>
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump
commons-io:commons-io from 2.13.0 to 2.15.0.</action>
diff --git
a/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
b/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
index cad2a2bba..b51e4b47a 100644
---
a/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
+++
b/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
@@ -164,13 +164,15 @@ public abstract class LZWInputStream extends
CompressorInputStream implements In
/**
* Initializes the arrays based on the maximum code size.
+ *
* @param maxCodeSize maximum code size
- * @throws IllegalArgumentException if {@code maxCodeSize} is not bigger
than 0
+ * @throws IllegalArgumentException if {@code maxCodeSize} is out of
bounds for {@code prefixes} and {@code characters}.
*/
protected void initializeTables(final int maxCodeSize) {
- if (maxCodeSize <= 0) {
- throw new IllegalArgumentException("maxCodeSize is " + maxCodeSize
- + ", must be bigger than 0");
+ // maxCodeSize shifted cannot be less than 256, otherwise the loop in
initializeTables() will throw an ArrayIndexOutOfBoundsException
+ // maxCodeSize cannot be smaller than getCodeSize(), otherwise
addEntry() will throw an ArrayIndexOutOfBoundsException
+ if (1 << maxCodeSize < 256 || getCodeSize() > maxCodeSize) {
+ throw new IllegalArgumentException("maxCodeSize is " + maxCodeSize
+ ", must be bigger than 0");
}
final int maxTableSize = 1 << maxCodeSize;
prefixes = new int[maxTableSize];
diff --git
a/src/test/java/org/apache/commons/compress/compressors/z/ZCompressorInputStreamTest.java
b/src/test/java/org/apache/commons/compress/compressors/z/ZCompressorInputStreamTest.java
index 793360f05..450909205 100644
---
a/src/test/java/org/apache/commons/compress/compressors/z/ZCompressorInputStreamTest.java
+++
b/src/test/java/org/apache/commons/compress/compressors/z/ZCompressorInputStreamTest.java
@@ -18,17 +18,20 @@
*/
package org.apache.commons.compress.compressors.z;
-import static org.apache.commons.compress.AbstractTest.getFile;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.nio.file.Files;
import java.util.Collections;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import org.apache.commons.compress.AbstractTest;
import org.apache.commons.compress.utils.IOUtils;
import org.junit.jupiter.api.Test;
@@ -45,9 +48,34 @@ public class ZCompressorInputStreamTest {
assertThrows(IOException.class, () -> new
ZCompressorInputStream(sequenceInputStream));
}
+ @Test
+ public void testInvalidMaxCodeSize() throws IOException {
+ final byte[] bytes =
Files.readAllBytes(AbstractTest.getPath("bla.tar.Z"));
+
+ // @formatter:off
+ final IntStream[] invalid = {
+ IntStream.range(Byte.MIN_VALUE, -120),
+ IntStream.range(-97, -88),
+ IntStream.range(-65, -56),
+ IntStream.range(-33, -24),
+ IntStream.range(-1, 8),
+ IntStream.range(31, 40),
+ IntStream.range(63, 72),
+ IntStream.range(95, 104),
+ IntStream.range(127, 127)
+ };
+ // @formatter:on
+
+ Stream.of(invalid).forEach(ints -> ints.forEach(i -> {
+ bytes[2] = (byte) i;
+ assertThrows(IllegalArgumentException.class, () -> new
ZCompressorInputStream(new ByteArrayInputStream(bytes), 1024 * 1024),
+ () -> "value=" + i);
+ }));
+ }
+
@Test
public void testMultiByteReadConsistentlyReturnsMinusOneAtEof() throws
IOException {
- final File input = getFile("bla.tar.Z");
+ final File input = AbstractTest.getFile("bla.tar.Z");
final byte[] buf = new byte[2];
try (InputStream is = Files.newInputStream(input.toPath());
ZCompressorInputStream in = new ZCompressorInputStream(is)) {
@@ -59,7 +87,7 @@ public class ZCompressorInputStreamTest {
@Test
public void testSingleByteReadConsistentlyReturnsMinusOneAtEof() throws
IOException {
- final File input = getFile("bla.tar.Z");
+ final File input = AbstractTest.getFile("bla.tar.Z");
try (InputStream is = Files.newInputStream(input.toPath());
ZCompressorInputStream in = new ZCompressorInputStream(is)) {
IOUtils.toByteArray(in);