Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2023-34453: snappy-java/src/main/java/org/xerial/snappy/BitShuffle.java at master · xerial/snappy-java

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.

CVE
#vulnerability#apache#java#auth

/*-------------------------------------------------------------------------- * Copyright 2011 Taro L. Saito * * Licensed under the Apache License, Version 2.0 (the “License”); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an “AS IS” BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *--------------------------------------------------------------------------*/ //-------------------------------------- // snappy-java Project // // BitShuffle.java // Since: 2016/03/31 // // $URL$ // $Author$ //-------------------------------------- package org.xerial.snappy; import java.io.IOException; import java.nio.ByteBuffer; public class BitShuffle { static { try { impl = SnappyLoader.loadBitShuffleApi(); } catch (Exception e) { throw new ExceptionInInitializerError(e); } } /** * An instance of BitShuffleNative */ private static BitShuffleNative impl; /** * Apply a bit-shuffling filter into the content in the given input buffer. After bit-shuffling, * you can retrieve the shuffled data from the output buffer [pos() …limit()) * (shuffled data size = limit() - pos() = remaining()). * * @param input buffer[pos() … limit()) containing the input data * @param type element type of the input data * @param shuffled output of the shuffled data. Uses range [pos()…]. * @return byte size of the shuffled data. * @throws SnappyError when the input is not a direct buffer * @throws IllegalArgumentException when the input length is not a multiple of the given type size */ public static int shuffle(ByteBuffer input, BitShuffleType type, ByteBuffer shuffled) throws IOException { if (!input.isDirect()) { throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, “input is not a direct buffer”); } if (!shuffled.isDirect()) { throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, “destination is not a direct buffer”); } // input: input[pos(), limit()) // output: shuffled int uPos = input.position(); int uLen = input.remaining(); int typeSize = type.getTypeSize(); if (uLen % typeSize != 0) { throw new IllegalArgumentException("input length must be a multiple of the given type size: " + typeSize); } if (shuffled.remaining() < uLen) { throw new IllegalArgumentException(“not enough space for output”); } int numProcessed = impl.shuffleDirectBuffer(input, uPos, typeSize, uLen, shuffled, shuffled.position()); assert(numProcessed == uLen); // pos limit // [ …BBBBBBB…] shuffled.limit(shuffled.position() + numProcessed); return numProcessed; } /** * Apply a bit-shuffling filter into the input short array. * * @param input * @return bit-shuffled byte array * @throws IOException */ public static byte[] shuffle(short[] input) throws IOException { if (input.length * 2 < input.length) { throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length); } byte[] output = new byte[input.length * 2]; int numProcessed = impl.shuffle(input, 0, 2, input.length * 2, output, 0); assert(numProcessed == input.length * 2); return output; } /** * Apply a bit-shuffling filter into the input int array. * * @param input * @return bit-shuffled byte array * @throws IOException */ public static byte[] shuffle(int[] input) throws IOException { if (input.length * 4 < input.length) { throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length); } byte[] output = new byte[input.length * 4]; int numProcessed = impl.shuffle(input, 0, 4, input.length * 4, output, 0); assert(numProcessed == input.length * 4); return output; } /** * Apply a bit-shuffling filter into the input long array. * * @param input * @return bit-shuffled byte array * @throws IOException */ public static byte[] shuffle(long[] input) throws IOException { if (input.length * 8 < input.length) { throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length); } byte[] output = new byte[input.length * 8]; int numProcessed = impl.shuffle(input, 0, 8, input.length * 8, output, 0); assert(numProcessed == input.length * 8); return output; } /** * Apply a bit-shuffling filter into the input float array. * * @param input * @return bit-shuffled byte array * @throws IOException */ public static byte[] shuffle(float[] input) throws IOException { if (input.length * 4 < input.length) { throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length); } byte[] output = new byte[input.length * 4]; int numProcessed = impl.shuffle(input, 0, 4, input.length * 4, output, 0); assert(numProcessed == input.length * 4); return output; } /** * Apply a bit-shuffling filter into the input double array. * * @param input * @return bit-shuffled byte array * @throws IOException */ public static byte[] shuffle(double[] input) throws IOException { if (input.length * 8 < input.length) { throw new SnappyError(SnappyErrorCode.TOO_LARGE_INPUT, "input array size is too large: " + input.length); } byte[] output = new byte[input.length * 8]; int numProcessed = impl.shuffle(input, 0, 8, input.length * 8, output, 0); assert(numProcessed == input.length * 8); return output; } /** * Convert the input bit-shuffled byte array into an original array. The result is dumped * to the specified output buffer. * * @param shuffled buffer[pos() … limit()) containing the input shuffled data * @param type element type of the input data * @param output output of the the original data. It uses buffer[pos()…] * @return byte size of the unshuffled data. * @throws IOException when failed to unshuffle the given input * @throws SnappyError when the input is not a direct buffer * @throws IllegalArgumentException when the length of input shuffled data is not a multiple of the given type size */ public static int unshuffle(ByteBuffer shuffled, BitShuffleType type, ByteBuffer output) throws IOException { if (!shuffled.isDirect()) { throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, “input is not a direct buffer”); } if (!output.isDirect()) { throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, “destination is not a direct buffer”); } // input: input[pos(), limit()) // output: shuffled int uPos = shuffled.position(); int uLen = shuffled.remaining(); int typeSize = type.getTypeSize(); if (uLen % typeSize != 0) { throw new IllegalArgumentException("length of input shuffled data must be a multiple of the given type size: " + typeSize); } if (output.remaining() < uLen) { throw new IllegalArgumentException(“not enough space for output”); } int numProcessed = impl.unshuffleDirectBuffer(shuffled, uPos, typeSize, uLen, output, shuffled.position()); assert(numProcessed == uLen); // pos limit // [ …BBBBBBB…] shuffled.limit(shuffled.position() + numProcessed); return numProcessed; } /** * Convert the input bit-shuffled byte array into an original short array. * * @param input * @return a short array * @throws IOException */ public static short[] unshuffleShortArray(byte[] input) throws IOException { short[] output = new short[input.length / 2]; int numProcessed = impl.unshuffle(input, 0, 2, input.length, output, 0); assert(numProcessed == input.length); return output; } /** * Convert the input bit-shuffled byte array into an original int array. * * @param input * @return an int array * @throws IOException */ public static int[] unshuffleIntArray(byte[] input) throws IOException { int[] output = new int[input.length / 4]; int numProcessed = impl.unshuffle(input, 0, 4, input.length, output, 0); assert(numProcessed == input.length); return output; } /** * Convert the input bit-shuffled byte array into an original long array. * * @param input * @return a long array * @throws IOException */ public static long[] unshuffleLongArray(byte[] input) throws IOException { long[] output = new long[input.length / 8]; int numProcessed = impl.unshuffle(input, 0, 8, input.length, output, 0); assert(numProcessed == input.length); return output; } /** * Convert the input bit-shuffled byte array into an original float array. * * @param input * @return an float array * @throws IOException */ public static float[] unshuffleFloatArray(byte[] input) throws IOException { float[] output = new float[input.length / 4]; int numProcessed = impl.unshuffle(input, 0, 4, input.length, output, 0); assert(numProcessed == input.length); return output; } /** * Convert the input bit-shuffled byte array into an original double array. * * @param input * @return a double array * @throws IOException */ public static double[] unshuffleDoubleArray(byte[] input) throws IOException { double[] output = new double[input.length / 8]; int numProcessed = impl.unshuffle(input, 0, 8, input.length, output, 0); assert(numProcessed == input.length); return output; } }

Related news

CVE-2023-30994: Security Bulletin: IBM QRadar SIEM includes components with known vulnerabilities

IBM QRadar SIEM 7.5.0 uses weaker than expected cryptographic algorithms that could allow an attacker to decrypt highly sensitive information. IBM X-Force ID: 254138

Red Hat Security Advisory 2023-5165-01

Red Hat Security Advisory 2023-5165-01 - Red Hat AMQ Streams, based on the Apache Kafka project, offers a distributed backbone that allows microservices and other applications to share data with extremely high throughput and extremely low latency. Issues addressed include code execution, denial of service, deserialization, and integer overflow vulnerabilities.

RHSA-2023:5165: Red Hat Security Advisory: Red Hat AMQ Streams 2.5.0 release and security update

Red Hat AMQ Streams 2.5.0 is now available from the Red Hat Customer Portal. Red Hat Product Security has rated this update as having a security impact of Important. A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE link(s) in the References section.This content is licensed under the Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/). If you distribute this content, or a modified version of it, you must provide attribution to Red Hat Inc. and provide a link to the original. Related CVEs: * CVE-2021-37136: A flaw was found in Netty's netty-codec due to size restrictions for decompressed data in the Bzip2Decoder. By sending a specially-crafted input, a remote attacker could cause a denial of service. * CVE-2021-37137: A flaw was found in the Netty's netty-codec due to unrestricted chunk lengths in the SnappyFrameDecoder. By sending a speciall...

GHSA-pqr6-cmr2-h8hf: snappy-java's Integer Overflow vulnerability in shuffle leads to DoS

## Summary Due to unchecked multiplications, an integer overflow may occur, causing a fatal error. ## Impact Denial of Service ## Description The function [shuffle(int[] input)](https://github.com/xerial/snappy-java/blob/05c39b2ca9b5b7b39611529cc302d3d796329611/src/main/java/org/xerial/snappy/BitShuffle.java#L107) in the file [BitShuffle.java](https://github.com/xerial/snappy-java/blob/master/src/main/java/org/xerial/snappy/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. ```java public static byte[] shuffle(int[] input) throws IOException { byte[] output = new byte[input.length * 4]; int numProcessed = impl.shuffle(input, 0, 4, input.length * 4, output, 0); assert(numProcessed == input.length * 4); return output; } ``` Since the length is not tested, the multiplication by four can cause an integer overflow and become ...

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907