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 --------- Co-authored-by: Taro L. Saito --- src/main/java/org/xerial/snappy/Snappy.java | 36 ++++++++-- .../java/org/xerial/snappy/SnappyTest.java | 66 ++++++++++++++++++- 2 files changed, 94 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/xerial/snappy/Snappy.java b/src/main/java/org/xerial/snappy/Snappy.java index 5263e94b..14d17964 100755 --- a/src/main/java/org/xerial/snappy/Snappy.java +++ b/src/main/java/org/xerial/snappy/Snappy.java @@ -169,7 +169,11 @@ public static int compress(ByteBuffer uncompressed, ByteBuffer compressed) 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 } /** @@ -181,7 +185,11 @@ public static byte[] compress(char[] input) 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 } /** @@ -193,7 +201,11 @@ public static byte[] compress(double[] input) 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 } /** @@ -205,7 +217,11 @@ public static byte[] compress(float[] input) 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 } /** @@ -217,7 +233,11 @@ public static byte[] compress(int[] input) 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 } /** @@ -229,7 +249,11 @@ public static byte[] compress(long[] input) 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/test/java/org/xerial/snappy/SnappyTest.java b/src/test/java/org/xerial/snappy/SnappyTest.java index 55726e79..a9fa9ea0 100755 --- a/src/test/java/org/xerial/snappy/SnappyTest.java +++ b/src/test/java/org/xerial/snappy/SnappyTest.java @@ -19,7 +19,7 @@ // SnappyTest.java // Since: 2011/03/30 // -// $URL$ +// $URL$ // $Author$ //-------------------------------------- package org.xerial.snappy; @@ -331,8 +331,8 @@ public void isValidCompressedData() } } - /* + /* Tests happy cases for SnappyInputStream.read method - {0} */ @@ -385,6 +385,67 @@ public void isInvalidChunkLengthForSnappyInputStreamOutOfMemory() - 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]); + } + + /* + Tests happy cases for Snappy.compress + - char: 0, 10 */ @Test public void isValidArrayInputLengthForBitShuffleShuffle() @@ -435,5 +496,6 @@ public void isTooLargeLongArrayInputLengthForBitShuffleShuffle() throws Exceptio public void isTooLargeShortArrayInputLengthForBitShuffleShuffle() throws Exception { BitShuffle.shuffle(new short[Integer.MAX_VALUE / 2 + 1]); + } }