CVE-2023-34454 - Fatal Flaw in snappy-java’s Compression—How Integer Overflow Can Crash Your Java Application

snappy-java is a widely used, high-speed Java library for compression and decompression, especially valued in big data circles for its blazing fast performance. But in versions before 1.1.10.1, a simple unchecked multiplication in its code can lead to a catastrophic error. This post details the vulnerability, shows exploitable code paths, and explains with straightforward language how a miscalculation in memory allocation can take down your application.

What is CVE-2023-34454?

CVE-2023-34454 arises due to integer overflow. When snappy-java tries to process unusually large input, it can accidentally create a negative number where a positive one was expected. This can cause either a fatal Java runtime crash or an uncaught exception, making the bug not only exploitable, but also a risk for denial-of-service (DoS) attacks.

The following is a simplified version of the snappy-java bug

// In Snappy.java, vulnerable versions < 1.1.10.1:
public static byte[] compress(char[] input) throws IOException {
    int len = input.length * 2;  // <-- PROBLEM: possible integer overflow!
    return rawCompress(input, , len);
}

// In rawCompress():
private static byte[] rawCompress(char[] input, int offset, int len) throws IOException {
    int maxCompressedLength = impl.maxCompressedLength(len); // Native call
    byte[] buf = new byte[maxCompressedLength];  // <-- Can cause NegativeArraySizeException!
    // ...
}

len gets set to input.length * 2—no check for overflow.

- If input.length is large enough (e.g., slightly over Integer.MAX_VALUE / 2), multiplying by 2 wraps into a negative int!
- The native method maxCompressedLength doesn’t care about Java negative numbers (treats the value as unsigned).

If maxCompressedLength returns a negative value, Java throws NegativeArraySizeException.

- If by luck the value is positive but too low, compression overruns the buffer, causing a JVM Access Violation—an instant, fatal crash.

Exploiting the Bug

You don’t need to be a hacker to trigger this bug—just pass enormous arrays to the affected compression methods. For example:

// POC for NegativeArraySizeException
final int LARGE = Integer.MAX_VALUE / 2 + 1;
char[] bigInput = new char[LARGE];
try {
    byte[] result = Snappy.compress(bigInput);
    System.out.println("Success: " + result.length);
} catch (Exception e) {
    System.err.println("Caught: " + e);
}


*This code will crash with a NegativeArraySizeException.*

compress(short[] input)

Each uses a multiplication factor (e.g. *4, *8) that can easily overflow for sufficiently large array sizes.

Native Side: Why Is This Fatal?

Java arrays cannot have negative sizes. But if you pass the negative length into a native method, it could return a value (thinking it's unsigned). Then, when Java tries to allocate the array, it throws an exception—or worse, an under-allocated buffer leads to memory writes beyond the array bounds, causing a fatal Java Access Violation.

Unrecoverable crash: Fatal JVM errors kill your application with a hard exit.

- Denial of Service risk: Attackers, or even just buggy code, can abuse this to repeatedly crash your app, leading to outages.
- Potential security implications: While remote code execution is unlikely, crashing server processes is a classic DoS technique.

Update your dependency

implementation 'org.xerial.snappy:snappy-java:1.1.10.1'


or

<dependency>
    <groupId>org.xerial.snappy</groupId>
    <artifactId>snappy-java</artifactId>
    <version>1.1.10.1</version>
</dependency>

References

- Official CVE page: CVE-2023-34454
- Security Advisory on GitHub
- Commit that fixed the issue

Conclusion

snappy-java is lightning fast, but unchecked math can be dangerous. Always validate input sizes before performing arithmetic—especially if they’re going to native code! If you’re using snappy-java, update to 1.1.10.1 or later immediately to safeguard your Java apps from dead-simple crashes and denial-of-service exploits.

Timeline

Published on: 06/15/2023 17:15:00 UTC
Last modified on: 06/27/2023 16:04:00 UTC