Skip to main content
← All libraries
Compression · C

How to fuzz Zstandard (zstd)

zstd's FSE entropy coder has non-trivial table arithmetic that rewards fuzzing.

zstd is rapidly displacing gzip in Linux package managers, container images, and kernel modules. Its Finite State Entropy (FSE) coder and Huffman variant (HUF) involve compact table representations with pointer arithmetic that can miscalculate when table sizes are adversarially set.

Common bug classes

  • Heap buffer overflow in FSE decoding table pointer arithmetic
  • Out-of-bounds read in HUF symbol decode with crafted tree
  • Integer overflow in match/literal length combined sequence decode
  • Null dereference on empty frame content size declaration
  • Use-after-free in skippable frame parsing across context reuse

Recommended setup

Fuzzers

  • AFL++
  • libFuzzer
  • Honggfuzz

Sanitizers

  • ASan
  • UBSan

Harness scaffold

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <zstd.h>

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  size_t dsize = ZSTD_getFrameContentSize(data, size);
  if (dsize == ZSTD_CONTENTSIZE_ERROR) return 0;
  if (dsize == ZSTD_CONTENTSIZE_UNKNOWN) dsize = 256 * 1024;
  if (dsize > 4 * 1024 * 1024) return 0;
  void *dst = malloc(dsize + 1);
  if (dst) {
    ZSTD_decompress(dst, dsize + 1, data, size);
    free(dst);
  }
  return 0;
}

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

Start fuzzing Zstandard (zstd) on Fuzze.rs →

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