CVE-2023-34453 (Java, published 2023-06-15T17:15Z)
Description: value: snappy-java is a fast compressor/decompressor for Java. Due to unchecked multiplications, an integer overflow may occur in versions prior to 1.1.10.1, causing a fatal error.

The function `shuffle(int[] input)` in the file `BitShuffle.java` receives an array of integers and applies a bit shuffle on it. It does so by multiplying the length by 4 and passing it to the natively compiled shuffle function. Since the length is not tested, the multiplication by four can cause an integer overflow and become a smaller value than the true size, or even zero or negative. In the case of a negative value, a `java.lang.NegativeArraySizeException` exception will raise, which can crash the program. In a case of a value that is zero or too small, the code that afterwards references the shuffled array will assume a bigger size of the array, which might cause exceptions such as `java.lang.ArrayIndexOutOfBoundsException`.

The same issue exists also when using the `shuffle` functions that receive a double, float, long and short, each using a different multiplier that may cause the same issue.

Version 1.1.10.1 contains a patch for this vulnerability.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-190 \u2014 Integer Overflow or Wraparound
The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
Repository: https://github.com/xerial/snappy-java
Files changed:
src/main/java/org/xerial/snappy/BitShuffle.java
src/main/java/org/xerial/snappy/SnappyErrorCode.java
src/test/java/org/xerial/snappy/SnappyTest.java
Commit message: Merge pull request from GHSA-pqr6-cmr2-h8hf

* Fixed integer overflow by checking if multiplication result is smaller than original value

* Fixed integer overflow by checking if multiplication result is smaller than original value

* Fixed integer overflow by checking if multiplication result is smaller than original value

* imporved error messages and added happy and sad cases for unit test in SnappyTest.java

* switched SnappyError into ILLEGAL_ARGUMENT in SnappyErrorCode.java and Snappy.java

* wrote new and updated unit test methods

* updated comments in SnappyTest.java

* Fixed and updated unit tests in SnappyTest.java

Vulnerable code:
    UNSUPPORTED_PLATFORM(9);

Fixed code:
        if (input.length * 2 < input.length) {
            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
        }
        if (input.length * 4 < input.length) {
            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
        }
        if (input.length * 8 < input.length) {
            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
        }
        if (input.length * 4 < input.length) {
            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
        }
        if (input.length * 8 < input.length) {
            throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length);
        }
    UNSUPPORTED_PLATFORM(9),
    TOO_LARGE_INPUT(10);

    /*
    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 isValidArrayInputLengthForBitShuffleShuffle()
            throws Exception
    {
        byte[] b = BitShuffle.shuffle(new double[0]);
        byte[] c = BitShuffle.shuffle(new float[0]);
        byte[] d = BitShuffle.shuffle(new int[0]);
        byte[] e = BitShuffle.shuffle(new long[0]);
        byte[] f = BitShuffle.shuffle(new short[0]);
        byte[] n = BitShuffle.shuffle(new double[10]);
        byte[] o = BitShuffle.shuffle(new float[10]);
        byte[] p = BitShuffle.shuffle(new int[10]);
        byte[] q = BitShuffle.shuffle(new long[10]);
        byte[] r = BitShuffle.shuffle(new short[10]);
    }

    /*
    Tests sad cases for BitShuffle.shuffle method
    - Allocate a buffer whose byte size will be a bit larger than Integer.MAX_VALUE
    - double: 8
    - float: 4
    - int: 4
    - long: 8
    - short: 2
     */
    @Test(expected = SnappyError.class)
    public void isTooLargeDoubleArrayInputLengthForBitShuffleShuffle() throws Exception {
        BitShuffle.shuffle(new double[Integer.MAX_VALUE / 8 + 1]);
    }

    @Test(expected = SnappyError.class)
    public void isTooLargeFloatArrayInputLengthForBitShuffleShuffle() throws Exception {
        BitShuffle.shuffle(new float[Integer.MAX_VALUE / 4 + 1]);
    }

    @Test(expected = SnappyError.class)
    public void isTooLargeIntArrayInputLengthForBitShuffleShuffle() throws Exception {
        BitShuffle.shuffle(new float[Integer.MAX_VALUE / 4 + 1]);
    }

    @Test(expected = SnappyError.class)
    public void isTooLargeLongArrayInputLengthForBitShuffleShuffle() throws Exception {
        BitShuffle.shuffle(new long[Integer.MAX_VALUE / 8 + 1]);
    }

    @Test(expected = SnappyError.class)
    public void isTooLargeShortArrayInputLengthForBitShuffleShuffle() throws Exception {
        BitShuffle.shuffle(new short[Integer.MAX_VALUE / 2 + 1]);
    }