Skip to content

Commit d2d01a7

Browse files
authored
Fix remaining ArrayIndexOutOfBoundsExceptions in LZ4DecompressorTest (#6)
An ArrayIndexOutOfBoundsException could indicate either an out-of-bounds access, or invalid arguments (e.g. offset < 0). Since we want to detect the former in the fuzz tests, we need to make sure the latter doesn't happen. This PR: - Disables the ArrayIndexOutOfBoundsException catch so that it's reported by the fuzzer - Fixes a bug in the test where the src length was larger than allowed - Adjusts the LZ4JNIFastDecompressor to throw an LZ4Exception on empty input rather than an ArrayIndexOutOfBoundsExceptions (made by @Marcono1234; not security relevant, this only changes the exception. LZ4JNIFastDecompressor is also disabled by default due to CVE-2025-12183) With these changes, a quick fuzz run now only shows the native_fast_* tests failing, both with a segfault, which is expected due to CVE-2025-12183.
1 parent 999c401 commit d2d01a7

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

src/java/net/jpountz/lz4/LZ4JNIFastDecompressor.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,14 @@ final class LZ4JNIFastDecompressor extends LZ4FastDecompressor {
3434

3535
@Override
3636
public final int decompress(byte[] src, int srcOff, byte[] dest, int destOff, int destLen) {
37-
SafeUtils.checkRange(src, srcOff);
37+
int srcLen = src.length - srcOff;
38+
SafeUtils.checkRange(src, srcOff, srcLen);
3839
SafeUtils.checkRange(dest, destOff, destLen);
40+
41+
if (srcLen == 0) {
42+
throw new LZ4Exception("Empty src");
43+
}
44+
3945
final int result = LZ4JNI.LZ4_decompress_fast(src, null, srcOff, dest, null, destOff, destLen);
4046
if (result < 0) {
4147
throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
@@ -46,9 +52,14 @@ public final int decompress(byte[] src, int srcOff, byte[] dest, int destOff, in
4652
@Override
4753
public int decompress(ByteBuffer src, int srcOff, ByteBuffer dest, int destOff, int destLen) {
4854
ByteBufferUtils.checkNotReadOnly(dest);
49-
ByteBufferUtils.checkRange(src, srcOff);
55+
int srcLen = src.capacity() - srcOff;
56+
ByteBufferUtils.checkRange(src, srcOff, srcLen);
5057
ByteBufferUtils.checkRange(dest, destOff, destLen);
5158

59+
if (srcLen == 0) {
60+
throw new LZ4Exception("Empty src");
61+
}
62+
5263
if ((src.hasArray() || src.isDirect()) && (dest.hasArray() || dest.isDirect())) {
5364
byte[] srcArr = null, destArr = null;
5465
ByteBuffer srcBuf = null, destBuf = null;

src/test/net/jpountz/fuzz/LZ4DecompressorTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ private void test(FuzzedDataProvider data, LZ4Factory factory, boolean fast, boo
3131
if (fast) {
3232
factory.fastDecompressor().decompress(srcBuf, srcOff, destBuf, destOff, destLen);
3333
} else {
34-
factory.safeDecompressor().decompress(srcBuf, srcOff, src.length - srcOffEnd, destBuf, destOff, destLen);
34+
factory.safeDecompressor().decompress(srcBuf, srcOff, src.length - srcOffEnd - srcOff, destBuf, destOff, destLen);
3535
}
3636
} else {
3737
byte[] dest = new byte[destOff + destLen];
3838
if (fast) {
3939
factory.fastDecompressor().decompress(src, srcOff, dest, destOff, destLen);
4040
} else {
41-
factory.safeDecompressor().decompress(src, srcOff, src.length - srcOffEnd, dest, destOff);
41+
factory.safeDecompressor().decompress(src, srcOff, src.length - srcOffEnd - srcOff, dest, destOff);
4242
}
4343
}
44-
} catch (LZ4Exception | ArrayIndexOutOfBoundsException ignored) {
44+
} catch (LZ4Exception ignored) {
4545
}
4646
}
4747

0 commit comments

Comments
 (0)