Fuzz Test Random Bytes Input Crash in Python

A simple fuzz test generates random byte inputs and runs a parser to find unexpected crashes.

Easy Python 3.9+ Aug 9, 2026 Testing & modern typing 15 views 0 copies

Python code

45 lines
Python 3.9+
import random


def parse_header(data: bytes) -> dict:
    """Parse a fake binary header format."""
    if len(data) < 8:
        raise ValueError("header too short")

    magic = data[:4]
    if magic != b'PARS':
        raise ValueError("bad magic")

    version = data[4]
    if version != 1:
        raise ValueError("unsupported version")

    flags = data[5]
    if flags & 0x80:
        raise ValueError("invalid flag bit")

    payload_len = int.from_bytes(data[6:8], "big")
    if payload_len > 1000:
        raise ValueError("payload too large")

    return {"version": version, "flags": flags, "payload_len": payload_len}


def fuzz(num_trials: int = 10000) -> None:
    """Randomly generate inputs and look for crashes."""
    for _ in range(num_trials):
        length = random.randint(0, 20)
        data = bytes(random.getrandbits(8) for _ in range(length))
        try:
            parse_header(data)
        except ValueError:
            pass  # expected for malformed input
        except Exception as e:
            print(f"CRASH: input={data!r} -> {type(e).__name__}: {e}")
            return

    print(f"All {num_trials} fuzz trials passed without crashes.")


if __name__ == "__main__":
    fuzz(5000)

Output

stdout
All 5000 fuzz trials passed without crashes.

How it works

The fuzz test randomly generates byte strings of varying lengths and feeds them to parse_header. The function expects a specific binary format: 4 magic bytes, a version byte, a flags byte, and a 2-byte payload length. Expected malformed inputs raise ValueError, which is caught and ignored. Any other exception is treated as a crash and printed, ending the loop. This approach quickly uncovers assumptions in parsers that can lead to unexpected exceptions.

Common mistakes

  • Forgetting to catch `ValueError` and accidentally counting expected failures as crashes
  • Not seeding the random number generator for reproducible runs
  • Generating inputs that are too uniform, missing edge cases like empty or very long data

Variations

  1. Use a fixed tuple of edge-case inputs like `b''` and `b'PARS'` mixed with random data
  2. Use `hypothesis` or `property-based testing` frameworks for more structured fuzzing

Real-world use cases

  • Testing a binary protocol parser in a network service for robustness against malformed packets.
  • Validating that a file format parser handles corrupted files without crashing in a data ingestion pipeline.
  • Checking security-sensitive parsers (like deserializers) for vulnerabilities before deployment.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Testing & modern typing

Related tutorials and quizzes for this topic.