Skip to main content
← All libraries
Compression · C

How to fuzz LZ4

LZ4's speed comes from minimal safety checks — a single length miscalculation overflows.

LZ4's decode hot path is intentionally minimal for speed, meaning bounds checks are sparse and rely on caller-supplied size parameters. When those parameters are wrong or the compressed stream is crafted, the decoder can write outside the output buffer. LZ4 is used in Linux kernel, databases (ClickHouse, RocksDB), and container runtimes.

Common bug classes

  • Heap buffer overflow in match copy with overlapping offset
  • Integer overflow in token literal length accumulation
  • Out-of-bounds write in LZ4F frame checksum block
  • Negative array index via malformed match length encoding
  • Buffer over-read in LZ4HC block dependency chain

Recommended setup

Fuzzers

  • AFL++
  • libFuzzer

Sanitizers

  • ASan
  • UBSan

Harness scaffold

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <lz4.h>
#include <lz4frame.h>

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  /* Raw LZ4 block decode */
  char out[65536];
  LZ4_decompress_safe((const char *)data, out, (int)size, sizeof(out));
  /* LZ4 frame decode */
  LZ4F_dctx *ctx;
  if (LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION) == 0) {
    char fbuf[65536]; size_t dst_sz = sizeof(fbuf), src_sz = size;
    LZ4F_decompress(ctx, fbuf, &dst_sz, data, &src_sz, NULL);
    LZ4F_freeDecompressionContext(ctx);
  }
  return 0;
}

Save this as fuzz_target.cc, build with your compiler + sanitizer flags, and you have a working starting point.

Notable CVEs found by fuzzing

  • CVE-2021-3520
Start fuzzing LZ4 on Fuzze.rs →

Push the harness above + a Dockerfile. First month 50% off.