Skip to main content

Fuzz test Python modules with libFuzzer.

Project description

buildstatus

About

!!! UNDER CONSTRUCTION - DO NOT USE !!!

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.

Installation

$ apt install clang
$ pip install pyfuzzer

Example Usage

Use the default generic mutator when testing the module hello_world.

$ cd examples/hello_world
$ pyfuzzer hello_world hello_world.c
clang -fprofile-instr-generate -fcoverage-mapping -g -fsanitize=fuzzer -fsanitize=signed-integer-overflow -fno-sanitize-recover=all -I/usr/include/python3.7m hello_world.c module.c /home/erik/workspace/pyfuzzer/pyfuzzer/pyfuzzer.c -Wl,-Bsymbolic-functions -Wl,-z,relro -lpython3.7m -o hello_world
rm -f hello_world.profraw
./hello_world -max_total_time=1 -max_len=4096
INFO: Seed: 1479758674
INFO: Loaded 1 modules   (22 inline 8-bit counters): 22 [0x47446d, 0x474483),
INFO: Loaded 1 PC tables (22 PCs): 22 [0x4616e0,0x461840),
ModuleNotFoundError: No module named 'mutator'
INFO: A corpus is not provided, starting from an empty corpus
#2   INITED cov: 7 ft: 8 corp: 1/1b lim: 4 exec/s: 0 rss: 44Mb
#10  NEW    cov: 8 ft: 9 corp: 2/3b lim: 4 exec/s: 0 rss: 44Mb L: 2/2 MS: 3 ChangeByte-ChangeBit-CopyPart-
#11  NEW    cov: 9 ft: 10 corp: 3/6b lim: 4 exec/s: 0 rss: 44Mb L: 3/3 MS: 1 CopyPart-
#23  NEW    cov: 10 ft: 11 corp: 4/10b lim: 4 exec/s: 0 rss: 44Mb L: 4/4 MS: 2 CopyPart-CrossOver-
#1044738     DONE   cov: 10 ft: 11 corp: 4/10b lim: 4096 exec/s: 522369 rss: 44Mb
Done 1044738 runs in 2 second(s)
llvm-profdata merge -sparse hello_world.profraw -o hello_world.profdata
llvm-cov show hello_world -instr-profile=hello_world.profdata -ignore-filename-regex=\.h|pyfuzzer.c|module.c
    1|       |#include <Python.h>
    2|       |
    3|       |PyDoc_STRVAR(
    4|       |    tell_doc,
    5|       |    "tell(message)\n"
    6|       |    "--\n"
    7|       |    "Arguments: (message:bytes)\n");
    8|       |
    9|       |static PyObject *m_tell(PyObject *module_p, PyObject *message_p)
   10|  1.04M|{
   11|  1.04M|    Py_ssize_t size;
   12|  1.04M|    char* buf_p;
   13|  1.04M|    int res;
   14|  1.04M|    PyObject *res_p;
   15|  1.04M|
   16|  1.04M|    res = PyBytes_AsStringAndSize(message_p, &buf_p, &size);
   17|  1.04M|
   18|  1.04M|    if (res != -1) {
   19|  1.04M|        switch (size) {
   20|  1.04M|
   21|  1.04M|        case 0:
   22|  47.6k|            res_p = PyLong_FromLong(5);
   23|  47.6k|            break;
   24|  1.04M|
   25|  1.04M|        case 1:
   26|   107k|            res_p = PyBool_FromLong(1);
   27|   107k|            break;
   28|  1.04M|
   29|  1.04M|        case 2:
   30|   114k|            res_p = PyBytes_FromString("Hello!");
   31|   114k|            break;
   32|  1.04M|
   33|  1.04M|        default:
   34|   774k|            res_p = PyLong_FromLong(0);
   35|   774k|            break;
   36|      0|        }
   37|      0|    } else {
   38|      0|        Py_INCREF(Py_None);
   39|      0|        res_p = Py_None;
   40|      0|    }
   41|  1.04M|
   42|  1.04M|    return (res_p);
   43|  1.04M|}
   44|       |
   45|       |static struct PyMethodDef methods[] = {
   46|       |    { "tell", m_tell, METH_O, tell_doc},
   47|       |    { NULL }
   48|       |};
   49|       |
   50|       |static PyModuleDef module = {
   51|       |    PyModuleDef_HEAD_INIT,
   52|       |    .m_name = "hello_world",
   53|       |    .m_size = -1,
   54|       |    .m_methods = methods
   55|       |};
   56|       |
   57|       |PyMODINIT_FUNC PyInit_hello_world(void)
   58|      1|{
   59|      1|    return (PyModule_Create(&module));
   60|      1|}

Use a custom mutator when testing the module hello_world.

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

$ cd examples/hello_world
$ pyfuzzer -m mutator.py hello_world hello_world.c
...

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.5.0.tar.gz (6.2 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