VYPR
High severityOSV Advisory· Published Dec 12, 2025· Updated Dec 15, 2025

Aircompressor's Snappy and LZ4 Java-based decompressor implementation can leak information from reused output buffer

CVE-2025-67721

Description

Aircompressor is a library with ports of the Snappy, LZO, LZ4, and Zstandard compression algorithms to Java. In versions 3.3 and below, incorrect handling of malformed data in Java-based decompressor implementations for Snappy and LZ4 allow remote attackers to read previous buffer contents via crafted compressed input. With certain crafted compressed inputs, elements from the output buffer can end up in the uncompressed output, potentially leaking sensitive data. This is relevant for applications that reuse the same output buffer to uncompress multiple inputs. This can be the case of a web server that allocates a fix-sized buffer for performance purposes. There is similar vulnerability in GHSA-cmp6-m4wj-q63q. This issue is fixed in version 3.4.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
io.airlift:aircompressor-v3Maven
< 3.43.4
io.airlift:aircompressorMaven
< 2.0.32.0.3

Affected products

1

Patches

2
f2b489b39877

Fix LZ4 decompressor data leak when match offset is zero

https://github.com/airlift/aircompressorMartin TraversoDec 9, 2025via ghsa
3 files changed · +15 2
  • src/main/java/io/airlift/compress/v3/lz4/Lz4RawDecompressor.java+1 1 modified
    @@ -114,7 +114,7 @@ public static int decompress(
                 input += SIZE_OF_SHORT;
     
                 long matchAddress = output - offset;
    -            if (matchAddress < outputAddress) {
    +            if (matchAddress < outputAddress || matchAddress >= output) {
                     throw new MalformedInputException(input - inputAddress, "offset outside destination buffer");
                 }
     
    
  • src/test/java/io/airlift/compress/v3/lz4/AbstractTestLz4.java+1 1 modified
    @@ -63,6 +63,6 @@ void testMatchLengthOverflow()
             byte[] data = buffer.toByteArray();
     
             assertThatThrownBy(() -> getDecompressor().decompress(data, 0, data.length, new byte[2048], 0, 2048))
    -                .hasMessageMatching("Malformed input.*|Unknown error occurred.*");
    +                .hasMessageMatching("Malformed input.*|Unknown error occurred.*|offset outside destination buffer.*");
         }
     }
    
  • src/test/java/io/airlift/compress/v3/lz4/TestLz4.java+13 0 modified
    @@ -15,9 +15,13 @@
     
     import io.airlift.compress.v3.Compressor;
     import io.airlift.compress.v3.Decompressor;
    +import io.airlift.compress.v3.MalformedInputException;
     import io.airlift.compress.v3.thirdparty.JPountzLz4Compressor;
     import io.airlift.compress.v3.thirdparty.JPountzLz4Decompressor;
     import net.jpountz.lz4.LZ4Factory;
    +import org.junit.jupiter.api.Test;
    +
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
     
     class TestLz4
             extends AbstractTestLz4
    @@ -45,4 +49,13 @@ protected Decompressor getVerifyDecompressor()
         {
             return new JPountzLz4Decompressor(LZ4Factory.fastestInstance());
         }
    +
    +    @Test
    +    void testZeroMatchOffset()
    +    {
    +        byte[] compressed = new byte[] {15, 0, 0, -1, -1, -118, 49, -1, -1, 0};
    +        assertThatThrownBy(() -> getDecompressor().decompress(compressed, 0, compressed.length, new byte[1024], 0, 1024))
    +                .isInstanceOf(MalformedInputException.class)
    +                .hasMessageContaining("offset outside destination buffer: offset=3");
    +    }
     }
    
ff12c4d5757c

Fix data leak when snappy match offset is zero

https://github.com/airlift/aircompressorDain SundstromDec 9, 2025via ghsa
2 files changed · +14 1
  • src/main/java/io/airlift/compress/v3/snappy/SnappyRawDecompressor.java+1 1 modified
    @@ -150,7 +150,7 @@ private static int uncompressAll(
                     // bit 8).
                     int matchOffset = entry & 0x700;
                     matchOffset += trailer;
    -                if (matchOffset < 0) {
    +                if (matchOffset <= 0) {
                         throw new MalformedInputException(input - inputAddress);
                     }
     
    
  • src/test/java/io/airlift/compress/v3/snappy/TestSnappyJava.java+13 0 modified
    @@ -15,8 +15,12 @@
     
     import io.airlift.compress.v3.Compressor;
     import io.airlift.compress.v3.Decompressor;
    +import io.airlift.compress.v3.MalformedInputException;
     import io.airlift.compress.v3.thirdparty.XerialSnappyCompressor;
     import io.airlift.compress.v3.thirdparty.XerialSnappyDecompressor;
    +import org.junit.jupiter.api.Test;
    +
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
     
     class TestSnappyJava
             extends AbstractTestSnappy
    @@ -44,4 +48,13 @@ protected Decompressor getVerifyDecompressor()
         {
             return new XerialSnappyDecompressor();
         }
    +
    +    @Test
    +    void testZeroMatchOffsetFails()
    +    {
    +        byte[] zeroMatchOffset = new byte[] {16, 1, 0, 1, 0, 1, 0, 1, 0};
    +        assertThatThrownBy(() -> new SnappyJavaDecompressor().decompress(zeroMatchOffset, 0, zeroMatchOffset.length, new byte[64], 0, 64))
    +                .isInstanceOf(MalformedInputException.class)
    +                .hasMessageContaining("Malformed input: offset=2");
    +    }
     }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.