Skip to main content

Fuzz test Python modules with libFuzzer.

Project description

buildstatus

About

Use libFuzzer to fuzz test Python 3.6+ C extension modules.

Ideas

  • Use type annotations for less type errors in generic mutator.

  • Add support to fuzz test pure Python modules by generating C code from them using Cython.

  • Add a verbose option?

  • Print corpus after run?

Installation

clang 8 or later is required.

$ apt install clang
$ pip install pyfuzzer

Example Usage

Hello world

Use the default mutator pyfuzzer.mutators.random when testing the module hello_world.

$ cd examples/hello_world
$ pyfuzzer run hello_world hello_world.c
...

Print the function calls that found new code paths. This information is usually good input when writing unit tests.

$ pyfuzzer print_corpus
tell(b'') = 5
tell(b'@') = True
tell(None) raises:
Traceback (most recent call last):
  File "/home/erik/workspace/pyfuzzer/pyfuzzer/mutators/utils.py", line 18, in print_function
    res = func(*args)
TypeError: expected bytes, NoneType found
tell(b'@\x01\x00') = 0
tell(b'#@') = b'Hello!'

See the hello_world for full output.

Hello world fatal error

Similar to the previous example, but triggers a fatal error in one branch in the code.

$ cd examples/hello_world_fatal_error
$ pyfuzzer run hello_world hello_world.c
...
Fatal Python error: deallocating None

Current thread 0x00007f7ca99c2780 (most recent call first):
...

Print the function call that caused the crash.

$ pyfuzzer print_crashes
tell(b'..............................................') = None

See the hello_world_fatal_error for full output.

Custom mutator

Use the custom mutator hello_world_mutator when testing the module hello_world.

Testing with a custom mutator is often more efficient than using a generic one.

$ cd examples/hello_world_custom_mutator
$ pyfuzzer run -m hello_world_mutator.py hello_world hello_world.c
...

See the hello_world_custom_mutator for full output.

Mutators

A Mutator uses data from libFuzzer to test a module. A mutator must implement the function test_one_input(module, data), where module is the module under test and data is the data generated by libFuzzer (as a bytes object).

A minimal mutator fuzz testing a CRC-32 algorithm could look like below. It simply calls crc_32() with data as its only argument.

import traceback
from .pyfuzzer.mutators.utils import print_function

def test_one_input(module, data):
    module.crc_32(data)

def test_one_input_print(module, data):
     print_function(module.crc_32, [data])

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyfuzzer-0.9.0.tar.gz (7.9 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page