From d0042551e4a3509a725038eb9b2ad1f683674d94 Mon Sep 17 00:00:00 2001
From: aidanchiu1112 <108113174+aidanchiu1112@users.noreply.github.com>
Date: Wed, 14 Jun 2023 11:06:30 -0700
Subject: [PATCH] Merge pull request from GHSA-fjpj-2g6w-x25r

* Fixed integer overflow by checking if bytesize is bigger than input length, then throwing exception

* Fixed integer overflow by checking if bytesize is bigger than input length, then throwing exception

* Fixed integer overflow by checking if bytesize is bigger than input length, then throwing exception

* improved error messages by adding new error enum INPUT_TOO_LARGE in SnappyErrorCode.java, and added happy and sad cases in SnappyTest.java

* fixed mispelling: validArrayInputLength --> isInvalidArrayInputLength

* switched SnappyError into ILLEGAL_ARGUMENT in SnappyErrorCode.java and Snappy.java and fixed a typo in error comment

* Fix buffer size boundary tests

* Remove negative array size tests

* updated comments for unit test

Origin: https://github.com/xerial/snappy-java/commit/d0042551e4a3509a725038eb9b2ad1f683674d94

---
 src/main/java/org/xerial/snappy/Snappy.java   | 36 ++++++++--
 .../org/xerial/snappy/SnappyErrorCode.java    |  4 +-
 .../java/org/xerial/snappy/SnappyTest.java    | 65 +++++++++++++++++++
 3 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/xerial/snappy/Snappy.java b/src/main/java/org/xerial/snappy/Snappy.java
index dc81f7c..762be59 100755
--- a/src/main/java/org/xerial/snappy/Snappy.java
+++ b/src/main/java/org/xerial/snappy/Snappy.java
@@ -163,7 +163,11 @@ public class Snappy
     public static byte[] compress(char[] input)
             throws IOException
     {
-        return rawCompress(input, input.length * 2); // char uses 2 bytes
+        int byteSize = input.length * 2;
+        if (byteSize < input.length) {
+            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
+        }
+        return rawCompress(input, byteSize); // char uses 2 bytes
     }
 
     /**
@@ -175,7 +179,11 @@ public class Snappy
     public static byte[] compress(double[] input)
             throws IOException
     {
-        return rawCompress(input, input.length * 8); // double uses 8 bytes
+        int byteSize = input.length * 8;
+        if (byteSize < input.length) {
+            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
+        }
+        return rawCompress(input, byteSize); // double uses 8 bytes
     }
 
     /**
@@ -187,7 +195,11 @@ public class Snappy
     public static byte[] compress(float[] input)
             throws IOException
     {
-        return rawCompress(input, input.length * 4); // float uses 4 bytes
+        int byteSize = input.length * 4;
+        if (byteSize < input.length) {
+            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
+        }
+        return rawCompress(input, byteSize); // float uses 4 bytes
     }
 
     /**
@@ -199,7 +211,11 @@ public class Snappy
     public static byte[] compress(int[] input)
             throws IOException
     {
-        return rawCompress(input, input.length * 4); // int uses 4 bytes
+        int byteSize = input.length * 4;
+        if (byteSize < input.length) {
+            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
+        }
+        return rawCompress(input, byteSize); // int uses 4 bytes
     }
 
     /**
@@ -211,7 +227,11 @@ public class Snappy
     public static byte[] compress(long[] input)
             throws IOException
     {
-        return rawCompress(input, input.length * 8); // long uses 8 bytes
+        int byteSize = input.length * 8;
+        if (byteSize < input.length) {
+            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
+        }
+        return rawCompress(input, byteSize); // long uses 8 bytes
     }
 
     /**
@@ -223,7 +243,11 @@ public class Snappy
     public static byte[] compress(short[] input)
             throws IOException
     {
-        return rawCompress(input, input.length * 2); // short uses 2 bytes
+        int byteSize = input.length * 2;
+        if (byteSize < input.length) {
+            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
+        }
+        return rawCompress(input, byteSize); // short uses 2 bytes
     }
 
     /**
diff --git a/src/main/java/org/xerial/snappy/SnappyErrorCode.java b/src/main/java/org/xerial/snappy/SnappyErrorCode.java
index 4325b02..661ffd8 100755
--- a/src/main/java/org/xerial/snappy/SnappyErrorCode.java
+++ b/src/main/java/org/xerial/snappy/SnappyErrorCode.java
@@ -41,7 +41,9 @@ public enum SnappyErrorCode
     FAILED_TO_UNCOMPRESS(5),
     EMPTY_INPUT(6),
     INCOMPATIBLE_VERSION(7),
-    INVALID_CHUNK_SIZE(8);
+    INVALID_CHUNK_SIZE(8),
+    UNSUPPORTED_PLATFORM(9),
+    TOO_LARGE_INPUT(10);
 
     public final int id;
 
diff --git a/src/test/java/org/xerial/snappy/SnappyTest.java b/src/test/java/org/xerial/snappy/SnappyTest.java
index 730dae9..4a863e0 100755
--- a/src/test/java/org/xerial/snappy/SnappyTest.java
+++ b/src/test/java/org/xerial/snappy/SnappyTest.java
@@ -376,4 +376,69 @@ public class SnappyTest
             // But OutOfMemoryError will not be caught, and will still be thrown
         }
     }
+
+    /*
+    Tests happy cases for BitShuffle.shuffle method
+    - double: 0, 10
+    - float: 0, 10
+    - int: 0, 10
+    - long: 0, 10
+    - short: 0, 10
+     */
+    @Test
+    public void isValidArrayInputLength()
+            throws Exception {
+        byte[] a = Snappy.compress(new char[0]);
+        byte[] b = Snappy.compress(new double[0]);
+        byte[] c = Snappy.compress(new float[0]);
+        byte[] d = Snappy.compress(new int[0]);
+        byte[] e = Snappy.compress(new long[0]);
+        byte[] f = Snappy.compress(new short[0]);
+        byte[] g = Snappy.compress(new char[10]);
+        byte[] h = Snappy.compress(new double[10]);
+        byte[] i = Snappy.compress(new float[10]);
+        byte[] j = Snappy.compress(new int[10]);
+        byte[] k = Snappy.compress(new long[10]);
+        byte[] l = Snappy.compress(new short[10]);
+    }
+
+    /*
+    Tests sad cases for Snappy.compress
+    - Allocate a buffer whose byte size will be a bit larger than Integer.MAX_VALUE
+    - char
+    - double
+    - float
+    - int
+    - long
+    - short
+     */
+    @Test(expected = SnappyError.class)
+    public void isTooLargeDoubleArrayInputLength() throws Exception {
+        Snappy.compress(new double[Integer.MAX_VALUE / 8 + 1]);
+    }
+
+    @Test(expected = SnappyError.class)
+    public void isTooLargeCharArrayInputLength() throws Exception {
+        Snappy.compress(new char[Integer.MAX_VALUE / 2 + 1]);
+    }
+
+    @Test(expected = SnappyError.class)
+    public void isTooLargeFloatArrayInputLength() throws Exception {
+        Snappy.compress(new float[Integer.MAX_VALUE / 4 + 1]);
+    }
+
+    @Test(expected = SnappyError.class)
+    public void isTooLargeIntArrayInputLength() throws Exception {
+        Snappy.compress(new int[Integer.MAX_VALUE / 4 + 1]);
+    }
+
+    @Test(expected = SnappyError.class)
+    public void isTooLargeLongArrayInputLength() throws Exception {
+        Snappy.compress(new long[Integer.MAX_VALUE / 8 + 1]);
+    }
+
+    @Test(expected = SnappyError.class)
+    public void isTooLargeShortArrayInputLength() throws Exception {
+        Snappy.compress(new short[Integer.MAX_VALUE / 2 + 1]);
+    }
 }
-- 
2.33.0

