CVE-2023-34455 (Java, published 2023-06-15T18:15Z)
Description: value: snappy-java is a fast compressor/decompressor for Java. Due to use of an unchecked chunk length, an unrecoverable fatal error can occur in versions prior to 1.1.10.1.

The code in the function hasNextChunk in the fileSnappyInputStream.java checks if a given stream has more chunks to read. It does that by attempting to read 4 bytes. If it wasn’t possible to read the 4 bytes, the function returns false. Otherwise, if 4 bytes were available, the code treats them as the length of the next chunk.

In the case that the `compressed` variable is null, a byte array is allocated with the size given by the input data. Since the code doesn’t test the legality of the `chunkSize` variable, it is possible to pass a negative number (such as 0xFFFFFFFF which is -1), which will cause the code to raise a `java.lang.NegativeArraySizeException` exception. A worse case would happen when passing a huge positive value (such as 0x7FFFFFFF), which would raise the fatal `java.lang.OutOfMemoryError` error.

Version 1.1.10.1 contains a patch for this issue.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-770 \u2014 Allocation of Resources Without Limits or Throttling
The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
Repository: https://github.com/xerial/snappy-java
Files changed:
src/main/java/org/xerial/snappy/SnappyInputStream.java
src/test/java/org/xerial/snappy/SnappyTest.java
Commit message: Merge pull request from GHSA-qcwq-55hx-v3vh

* asserted chunksize should be in the bounds of 0-java.outofmmeoryexception

* asserted chunksize should be in the bounds of 0-java.outofmmeoryexception

* https://github.com/xerial/snappy-java-ghsa-qcwq-55hx-v3vh/pull/2

* advisory-fix-3

* added and changed method name for happy and sad cases in SnappyTest.java

* removed expected error for happy case in unit testing

* added another unit test case in SnappyTest.java and fixed comments in SnappyInputStream.java

* switched SnappyError to INVALID_CHUNK_SIZE

* Updated unit tests

* Resolved conflicts with another PR merge

Vulnerable code:
            compressed = new byte[chunkSize];
     */

Fixed code:
        // chunkSize is negative
        if (chunkSize < 0) {
            throw new SnappyError(SnappyErrorCode.INVALID_CHUNK_SIZE, "chunkSize is too big or negative : " + chunkSize);
        }

            // chunkSize exceeds limit
            try {
                compressed = new byte[chunkSize];
            }
            catch (java.lang.OutOfMemoryError e) {
                throw new SnappyError(SnappyErrorCode.INVALID_CHUNK_SIZE, e.getMessage());
            }
import java.io.ByteArrayInputStream;
    /*

    Tests happy cases for SnappyInputStream.read method
    - {0}
     */
    @Test
    public void isValidChunkLengthForSnappyInputStreamIn()
            throws Exception {
        byte[] data = {0};
        SnappyInputStream in = new SnappyInputStream(new ByteArrayInputStream(data));
        byte[] out = new byte[50];
        in.read(out);
    }

    /*
    Tests sad cases for SnappyInputStream.read method
    - Expects a java.lang.NegativeArraySizeException catched into a SnappyError
    - {-126, 'S', 'N', 'A', 'P', 'P', 'Y', 0, 0, 0, 0, 0, 0, 0, 0, 0,(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff}
     */
    @Test(expected = SnappyError.class)
    public void isInvalidChunkLengthForSnappyInputStreamInNegative()
            throws Exception {
        byte[] data = {-126, 'S', 'N', 'A', 'P', 'P', 'Y', 0, 0, 0, 0, 0, 0, 0, 0, 0,(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff};
        SnappyInputStream in = new SnappyInputStream(new ByteArrayInputStream(data));
        byte[] out = new byte[50];
        in.read(out);
    }

    /*
    Tests sad cases for SnappyInputStream.read method
    - Expects a java.lang.OutOfMemoryError
    - {-126, 'S', 'N', 'A', 'P', 'P', 'Y', 0, 0, 0, 0, 0, 0, 0, 0, 0,(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff}
     */
    @Test(expected = SnappyError.class)
    public void isInvalidChunkLengthForSnappyInputStreamOutOfMemory()
            throws Exception {
        byte[] data = {-126, 'S', 'N', 'A', 'P', 'P', 'Y', 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff};
        SnappyInputStream in = new SnappyInputStream(new ByteArrayInputStream(data));
        byte[] out = new byte[50];
        try {
            in.read(out);
        } catch (Exception ignored) {
            // Exception here will be catched
            // But OutOfMemoryError will not be caught, and will still be thrown
        }
    }

    */