{"id":18913568,"url":"https://github.com/eerimoq/pyfuzzer","last_synced_at":"2025-04-15T08:30:52.945Z","repository":{"id":62580472,"uuid":"212747606","full_name":"eerimoq/pyfuzzer","owner":"eerimoq","description":"Fuzz test Python modules with libFuzzer","archived":false,"fork":false,"pushed_at":"2022-03-20T17:36:26.000Z","size":92,"stargazers_count":24,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T18:50:40.705Z","etag":null,"topics":["fuzzing","libfuzzer"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eerimoq.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-04T06:11:52.000Z","updated_at":"2024-11-28T16:34:30.000Z","dependencies_parsed_at":"2022-11-03T22:01:00.700Z","dependency_job_id":null,"html_url":"https://github.com/eerimoq/pyfuzzer","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fpyfuzzer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fpyfuzzer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fpyfuzzer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fpyfuzzer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eerimoq","download_url":"https://codeload.github.com/eerimoq/pyfuzzer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248585289,"owners_count":21128974,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fuzzing","libfuzzer"],"created_at":"2024-11-08T10:08:16.734Z","updated_at":"2025-04-15T08:30:52.680Z","avatar_url":"https://github.com/eerimoq.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"|buildstatus|_\n|coverage|_\n\nAbout\n=====\n\nUse `libFuzzer`_ to fuzz test Python 3.6+ C extension modules.\n\nInstallation\n============\n\n`clang 8` or later is required.\n\n.. code-block:: text\n\n   $ apt install clang\n   $ pip install pyfuzzer\n\nExample Usage\n=============\n\nHello world\n-----------\n\nUse the default mutator ``pyfuzzer.mutators.generic`` when testing the\nmodule ``hello_world``.\n\n.. code-block:: text\n\n   $ cd examples/hello_world\n   $ pyfuzzer run -l max_total_time=1 hello_world.c\n   \u003clots of libFuzzer output\u003e\n\nPrint the function calls that found new code paths. This information\nis usually useful when writing unit tests.\n\n.. code-block:: text\n\n   $ pyfuzzer print_corpus\n   corpus/25409981b15b978c9fb5a5a2f4dab0c4b04e295f:\n       tell(b'') = 5\n   corpus/a8a4e6c9abfd3c6cba171579190702ddc1317df0:\n       tell(b'\\xfd#') = b'Hello!'\n   corpus/80f87702ef9fbe4baf17095c79ff928b9fa1ea14:\n       tell(b'\\x00') = True\n   corpus/be3d1b7df189727b2cecd6526aa8f24abbf6df10:\n       tell(b'\\x00\\xfd\\x00') = 0\n   corpus/defd8787d638f271cd83362eafe7fdeed9fa4a8f:\n       tell(None) raises:\n       Traceback (most recent call last):\n         File \"/home/erik/workspace/pyfuzzer/pyfuzzer/mutators/utils.py\", line 35, in print_callable\n           res = obj(*args)\n       TypeError: expected bytes, NoneType found\n\nSee the `hello_world`_ for all files.\n\nHello world fatal error\n-----------------------\n\nSimilar to the previous example, but triggers a fatal error when\n``tell()`` is called with a bytes object longer than 2 bytes as its\nfirst argument.\n\n.. code-block:: text\n\n   $ cd examples/hello_world_fatal_error\n   $ pyfuzzer run hello_world.c\n   ...\n   Fatal Python error: deallocating None\n\n   Current thread 0x00007f7ca99c2780 (most recent call first):\n   ...\n\nPrint the function call that caused the crash. Just as expected, the\nfirst argument is clearly longer than 2 bytes.\n\n.. code-block:: text\n\n   $ pyfuzzer print_crashes\n   crash-1013ed88cd71fd14407b2bdbc17b95d7bc317c21:\n       tell(b'\\n\\xbf+') = None\n\nSee the `hello_world_fatal_error`_ for all files.\n\nCustom mutator\n--------------\n\nUse the custom mutator ``hello_world_mutator`` when testing the module\n``hello_world``.\n\nTesting with a custom mutator is often more efficient than using a\ngeneric one.\n\n.. code-block:: text\n\n   $ cd examples/hello_world_custom_mutator\n   $ pyfuzzer run -l max_total_time=1 -m hello_world_mutator.py hello_world.c\n   ...\n\nSee the `hello_world_custom_mutator`_ for all files.\n\nMutators\n========\n\nA mutator module uses data from `libFuzzer`_ to test a module. A\nmutator module must implement the function ``setup(module)``, where\n``module`` is the module under test. It shall return a mutator\ninstance that implements the methods ``test_one_input(self, data)``\nand ``test_one_input_print(self, data)``, where ``data`` is the data\ngenerated by `libFuzzer`_ (as a bytes object).\n\n``test_one_input(self, data)`` performs the actual fuzz testing, while\n``test_one_input_print(self, data)`` prints corpus and crashes.\n\nA minimal mutator fuzz testing a CRC-32 algorithm could look like\nbelow. It simply calls ``crc_32()`` with ``data`` as its only\nargument.\n\n.. code-block:: python\n\n   from pyfuzzer.mutators.generic import print_callable\n\n   class Mutator:\n\n       def __init__(self, module):\n           self._module = module\n\n       def test_one_input(self, data):\n           return self._module.crc_32(data)\n\n       def test_one_input_print(self, data):\n           print_callable(self._module.crc_32, [data])\n\n    def setup(module):\n        return Mutator(module)\n\nIdeas\n=====\n\n- Add support to fuzz test pure Python modules by generating C code\n  using Cython.\n\n.. |buildstatus| image:: https://travis-ci.org/eerimoq/pyfuzzer.svg\n.. _buildstatus: https://travis-ci.org/eerimoq/pyfuzzer\n\n.. |coverage| image:: https://coveralls.io/repos/github/eerimoq/pyfuzzer/badge.svg?branch=master\n.. _coverage: https://coveralls.io/github/eerimoq/pyfuzzer\n\n.. _libFuzzer: https://llvm.org/docs/LibFuzzer.html\n\n.. _hello_world: https://github.com/eerimoq/pyfuzzer/tree/master/examples/hello_world\n\n.. _hello_world_fatal_error: https://github.com/eerimoq/pyfuzzer/tree/master/examples/hello_world_fatal_error\n\n.. _hello_world_custom_mutator: https://github.com/eerimoq/pyfuzzer/tree/master/examples/hello_world_custom_mutator\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feerimoq%2Fpyfuzzer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feerimoq%2Fpyfuzzer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feerimoq%2Fpyfuzzer/lists"}