Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/eerimoq/pyfuzzer
Fuzz test Python modules with libFuzzer
https://github.com/eerimoq/pyfuzzer
fuzzing libfuzzer
Last synced: 3 months ago
JSON representation
Fuzz test Python modules with libFuzzer
- Host: GitHub
- URL: https://github.com/eerimoq/pyfuzzer
- Owner: eerimoq
- License: mit
- Created: 2019-10-04T06:11:52.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-03-20T17:36:26.000Z (almost 3 years ago)
- Last Synced: 2024-10-07T02:05:57.874Z (4 months ago)
- Topics: fuzzing, libfuzzer
- Language: Python
- Homepage:
- Size: 89.8 KB
- Stars: 25
- Watchers: 3
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.rst
- License: LICENSE
Awesome Lists containing this project
README
|buildstatus|_
|coverage|_About
=====Use `libFuzzer`_ to fuzz test Python 3.6+ C extension modules.
Installation
============`clang 8` or later is required.
.. code-block:: text
$ apt install clang
$ pip install pyfuzzerExample Usage
=============Hello world
-----------Use the default mutator ``pyfuzzer.mutators.generic`` when testing the
module ``hello_world``... code-block:: text
$ cd examples/hello_world
$ pyfuzzer run -l max_total_time=1 hello_world.c
Print the function calls that found new code paths. This information
is usually useful when writing unit tests... code-block:: text
$ pyfuzzer print_corpus
corpus/25409981b15b978c9fb5a5a2f4dab0c4b04e295f:
tell(b'') = 5
corpus/a8a4e6c9abfd3c6cba171579190702ddc1317df0:
tell(b'\xfd#') = b'Hello!'
corpus/80f87702ef9fbe4baf17095c79ff928b9fa1ea14:
tell(b'\x00') = True
corpus/be3d1b7df189727b2cecd6526aa8f24abbf6df10:
tell(b'\x00\xfd\x00') = 0
corpus/defd8787d638f271cd83362eafe7fdeed9fa4a8f:
tell(None) raises:
Traceback (most recent call last):
File "/home/erik/workspace/pyfuzzer/pyfuzzer/mutators/utils.py", line 35, in print_callable
res = obj(*args)
TypeError: expected bytes, NoneType foundSee the `hello_world`_ for all files.
Hello world fatal error
-----------------------Similar to the previous example, but triggers a fatal error when
``tell()`` is called with a bytes object longer than 2 bytes as its
first argument... code-block:: text
$ cd examples/hello_world_fatal_error
$ pyfuzzer run hello_world.c
...
Fatal Python error: deallocating NoneCurrent thread 0x00007f7ca99c2780 (most recent call first):
...Print the function call that caused the crash. Just as expected, the
first argument is clearly longer than 2 bytes... code-block:: text
$ pyfuzzer print_crashes
crash-1013ed88cd71fd14407b2bdbc17b95d7bc317c21:
tell(b'\n\xbf+') = NoneSee the `hello_world_fatal_error`_ for all files.
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... code-block:: text
$ cd examples/hello_world_custom_mutator
$ pyfuzzer run -l max_total_time=1 -m hello_world_mutator.py hello_world.c
...See the `hello_world_custom_mutator`_ for all files.
Mutators
========A mutator module uses data from `libFuzzer`_ to test a module. A
mutator module must implement the function ``setup(module)``, where
``module`` is the module under test. It shall return a mutator
instance that implements the methods ``test_one_input(self, data)``
and ``test_one_input_print(self, data)``, where ``data`` is the data
generated by `libFuzzer`_ (as a bytes object).``test_one_input(self, data)`` performs the actual fuzz testing, while
``test_one_input_print(self, data)`` prints corpus and crashes.A minimal mutator fuzz testing a CRC-32 algorithm could look like
below. It simply calls ``crc_32()`` with ``data`` as its only
argument... code-block:: python
from pyfuzzer.mutators.generic import print_callable
class Mutator:
def __init__(self, module):
self._module = moduledef test_one_input(self, data):
return self._module.crc_32(data)def test_one_input_print(self, data):
print_callable(self._module.crc_32, [data])def setup(module):
return Mutator(module)Ideas
=====- Add support to fuzz test pure Python modules by generating C code
using Cython... |buildstatus| image:: https://travis-ci.org/eerimoq/pyfuzzer.svg
.. _buildstatus: https://travis-ci.org/eerimoq/pyfuzzer.. |coverage| image:: https://coveralls.io/repos/github/eerimoq/pyfuzzer/badge.svg?branch=master
.. _coverage: https://coveralls.io/github/eerimoq/pyfuzzer.. _libFuzzer: https://llvm.org/docs/LibFuzzer.html
.. _hello_world: https://github.com/eerimoq/pyfuzzer/tree/master/examples/hello_world
.. _hello_world_fatal_error: https://github.com/eerimoq/pyfuzzer/tree/master/examples/hello_world_fatal_error
.. _hello_world_custom_mutator: https://github.com/eerimoq/pyfuzzer/tree/master/examples/hello_world_custom_mutator