elastic/elasticsearch · error · LZ4Exception
Too large matchLen
Error message
Too large matchLen
What it means
When the match-length nibble equals ML_MASK (15), the decoder reads 0xFF extension bytes adding 255 each. If matchLen overflows int (goes negative), the declared match length is implausibly large and the stream is malformed. This bounds the variable-length match encoding symmetrically with the literal-length check.
Source
Thrown at libs/lz4/src/main/java/org/elasticsearch/lz4/ESLZ4Decompressor.java:134
sOff += literalLen;
dOff = literalCopyEnd;
// matchs
final int matchDec = SafeUtils.readShortLE(src, sOff);
sOff += 2;
int matchOff = dOff - matchDec;
if (matchOff < destOff) {
throw new LZ4Exception("Malformed input at " + sOff);
}
int matchLen = token & LZ4Constants.ML_MASK;
if (matchLen == LZ4Constants.ML_MASK) {
byte len = (byte) 0xFF;
while (sOff < srcEnd && (len = SafeUtils.readByte(src, sOff++)) == (byte) 0xFF) {
matchLen += 0xFF;
if (matchLen < 0) {
throw new LZ4Exception("Too large matchLen");
}
}
matchLen += len & 0xFF;
}
matchLen += LZ4Constants.MIN_MATCH;
final int matchCopyEnd = dOff + matchLen;
// Check for overflow
if (matchCopyEnd < dOff) {
throw new LZ4Exception("Too large matchLen");
}
if (matchDec == 0) {
if (matchCopyEnd > destEnd) {
throw new LZ4Exception("Malformed input at " + sOff);
}
// With matchDec == 0, matchOff == dOff, so we'd copy in place. Zero the data instead. (CVE-2025-66566)
assert matchOff == dOff; // should always hold, but this extra check will trigger during fuzzing if my logic is wrongView on GitHub (pinned to db6a809a66)
Solutions
- Discard the corrupt block; recover from a known-good source.
- Validate the compressor that produced the input.
- If recurring, audit the storage path for corruption.
Defensive patterns
Strategy: try-catch
Validate before calling
// Heuristic upper bound on match length vs destLen
if (destLen < 0 || destLen > src.length * 255L) {
throw new IllegalArgumentException("Implausible destLen for match-length bounds");
} Try / catch
try {
ESLZ4Decompressor.INSTANCE.decompress(src, srcOff, dest, destOff, destLen);
} catch (LZ4Exception e) {
markCorruptAndRecover();
} Prevention
- Reject implausible destLen before decompression.
- Treat match-length overflow as corrupt/adversarial input.
- Recover from a known-good source on any LZ4Exception.
When it happens
Trigger: Decompressing a block whose match-length extension bytes sum beyond Integer.MAX_VALUE - i.e. an unbounded run of 0xFF before the terminating length byte in the match section. Indicates crafted or heavily corrupt input.
Common situations: Fuzzed/adversarial LZ4 input. Memory corruption overwriting match-length bytes with 0xFF. Incompatible compressor output.
Related errors
- Too large literalLen
- Malformed input at {}
- Failed when reading jar file ${path}
- time value cannot store values greater than 106751 days
- Resolution overflow
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/c4ba9fd08a42e477.
Report an issue: GitHub.