CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-atheris

A coverage-guided fuzzer for Python and Python extensions based on libFuzzer

91

1.28x
Overview
Eval results
Files

core-fuzzing.mddocs/

Core Fuzzing Functions

Essential functions for setting up and running the Atheris fuzzer. These functions provide the fundamental fuzzing capabilities including configuration, execution control, and input mutation.

Capabilities

Setup and Configuration

Configure the fuzzer with your test function and options before starting the fuzzing process.

def Setup(args, test_one_input, **kwargs):
    """
    Configure the fuzzer with test function and options.
    
    Args:
        args (list): Command-line arguments, typically sys.argv. This list may be
                    modified in-place to remove arguments consumed by the fuzzer.
        test_one_input (callable): Your fuzzer's entry point function. Must accept
                                  a single bytes argument and perform the testing.
        **kwargs: Optional keyword arguments:
            internal_libfuzzer (bool, optional): Controls libfuzzer mode:
                                               - None: Auto-detect (default)
                                               - True: Use internal libfuzzer
                                               - False: Use external libfuzzer
            custom_mutator (callable, optional): Custom mutation function with signature:
                                               (data: bytes, max_size: int, seed: int) -> bytes
            custom_crossover (callable, optional): Custom crossover function with signature:
                                                 (data1: bytes, data2: bytes, max_out_size: int, seed: int) -> bytes
    
    Returns:
        list: Remaining command-line arguments after fuzzer argument consumption
    """

Usage Example:

import atheris
import sys

def TestOneInput(data):
    # Your fuzzing logic here
    some_function_to_test(data)

# Basic setup
atheris.Setup(sys.argv, TestOneInput)

# Setup with custom mutator
def custom_mutator(data, max_size, seed):
    # Custom mutation logic
    return mutated_data

atheris.Setup(sys.argv, TestOneInput, custom_mutator=custom_mutator)

Fuzzing Execution

Start and control the fuzzing process.

def Fuzz():
    """
    Start the fuzzing loop. Must call Setup() first.
    
    This function takes control of the program and does not return under normal
    circumstances. The fuzzer will run until one of these conditions:
    - A crash is found (uncaught exception in test_one_input)
    - Run limits are reached (via command-line flags)
    - External termination (SIGINT, SIGTERM, etc.)
    - libFuzzer exits due to other conditions
    
    Raises:
        RuntimeError: If Setup() was not called first
    """

Usage Example:

# Must call Setup() before Fuzz()
atheris.Setup(sys.argv, TestOneInput)

# Start fuzzing - this call does not return
atheris.Fuzz()

# Code after this point will not be reached
print("This will never be printed")

Input Mutation

Access libFuzzer's built-in mutation capabilities for custom mutators.

def Mutate(data, max_size):
    """
    Mutate input data using libFuzzer's built-in mutator.
    
    This function provides access to the same mutation algorithms that libFuzzer
    uses internally. Useful for implementing custom mutators that combine
    domain-specific mutations with libFuzzer's general-purpose mutations.
    
    Args:
        data (bytes): Input data to mutate. Can be empty bytes.
        max_size (int): Maximum size of the mutated output in bytes.
                       The actual output may be smaller than this limit.
    
    Returns:
        bytes: Mutated data. The length will be <= max_size.
    """

Usage Example:

def CustomMutator(data, max_size, seed):
    # Use libFuzzer's built-in mutation as a base
    mutated = atheris.Mutate(data, max_size)
    
    # Apply domain-specific mutations
    if len(mutated) > 4:
        # Example: occasionally corrupt a magic header
        if seed % 10 == 0:
            mutated = b"CORRUPT" + mutated[4:]
    
    return mutated

atheris.Setup(sys.argv, TestOneInput, custom_mutator=CustomMutator)
atheris.Fuzz()

Command-Line Integration

Atheris processes command-line arguments to configure fuzzing behavior. Common options include:

  • -atheris_runs=N: Limit fuzzing to N executions
  • -max_len=N: Maximum input length
  • -timeout=N: Timeout in seconds for each execution
  • -dict=file: Use dictionary file for mutations
  • -jobs=N: Number of parallel fuzzing jobs
  • -workers=N: Number of simultaneous worker processes

Usage Example:

import sys
import atheris

def TestOneInput(data):
    target_function(data)

# sys.argv might contain: ['fuzzer.py', '-atheris_runs=1000', '-max_len=100']
remaining_args = atheris.Setup(sys.argv, TestOneInput)
print(f"Remaining arguments: {remaining_args}")

atheris.Fuzz()

Error Handling

Atheris reports failures when the test function throws uncaught exceptions:

def TestOneInput(data):
    try:
        risky_function(data)
    except ExpectedException:
        # Expected exceptions should be caught - they don't indicate bugs
        pass
    # Uncaught exceptions will be reported as crashes by Atheris

For debugging, you can limit runs and examine specific inputs:

# Run fuzzer for limited iterations to debug
# Command: python fuzzer.py -atheris_runs=10

def TestOneInput(data):
    print(f"Testing with {len(data)} bytes: {data[:10]}...")
    target_function(data)

Install with Tessl CLI

npx tessl i tessl/pypi-atheris

docs

advanced-features.md

core-fuzzing.md

data-provider.md

index.md

instrumentation.md

tile.json