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 <garydgreg...@gmail.com>
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);

Reply via email to