contrib/fuzz/manifest.cc
changeset 40054 8c692a6b5ad1
child 40090 3418f83c8874
equal deleted inserted replaced
40053:55db747a21ad 40054:8c692a6b5ad1
       
     1 #include <Python.h>
       
     2 #include <assert.h>
       
     3 #include <stdlib.h>
       
     4 #include <unistd.h>
       
     5 
       
     6 #include <string>
       
     7 
       
     8 extern "C" {
       
     9 
       
    10 /* TODO: use Python 3 for this fuzzing? */
       
    11 PyMODINIT_FUNC initparsers(void);
       
    12 
       
    13 static char cpypath[8192] = "\0";
       
    14 
       
    15 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
       
    16 {
       
    17 	const std::string subdir = "/sanpy/lib/python2.7";
       
    18 	/* HACK ALERT: we need a full Python installation built without
       
    19 	   pymalloc and with ASAN, so we dump one in
       
    20 	   $OUT/sanpy/lib/python2.7. This helps us wire that up. */
       
    21 	std::string selfpath(*argv[0]);
       
    22 	std::string pypath;
       
    23 	auto pos = selfpath.rfind("/");
       
    24 	if (pos == std::string::npos) {
       
    25 		char wd[8192];
       
    26 		getcwd(wd, 8192);
       
    27 		pypath = std::string(wd) + subdir;
       
    28 	} else {
       
    29 		pypath = selfpath.substr(0, pos) + subdir;
       
    30 	}
       
    31 	strncpy(cpypath, pypath.c_str(), pypath.size());
       
    32 	setenv("PYTHONPATH", cpypath, 1);
       
    33 	Py_SetPythonHome(cpypath);
       
    34 	return 0;
       
    35 }
       
    36 
       
    37 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
       
    38 {
       
    39 	Py_InitializeEx(0);
       
    40 	initparsers();
       
    41 	PyObject *mtext =
       
    42 	    PyBytes_FromStringAndSize((const char *)Data, (Py_ssize_t)Size);
       
    43 	PyObject *mainmod = PyImport_AddModule("__main__");
       
    44 	PyObject *globals = PyModule_GetDict(mainmod);
       
    45 	PyObject *locals = PyDict_New();
       
    46 	PyDict_SetItemString(locals, "mdata", mtext);
       
    47 	PyCodeObject *code =
       
    48 	    (PyCodeObject *)Py_CompileString(R"py(
       
    49 from parsers import lazymanifest
       
    50 lm = lazymanifest(mdata)
       
    51 try:
       
    52   # iterate the whole thing, which causes the code to fully parse
       
    53   # every line in the manifest
       
    54   list(lm.iterentries())
       
    55   lm[b'xyzzy'] = (b'\0' * 20, 'x')
       
    56   # do an insert, text should change
       
    57   assert lm.text() != mdata, "insert should change text and didn't: %r %r" % (lm.text(), mdata)
       
    58   del lm[b'xyzzy']
       
    59   # should be back to the same
       
    60   assert lm.text() == mdata, "delete should have restored text but didn't: %r %r" % (lm.text(), mdata)
       
    61 except Exception as e:
       
    62   pass
       
    63   # uncomment this print if you're editing this Python code
       
    64   # to debug failures.
       
    65   # print e
       
    66 )py",
       
    67 	                                     "fuzzer", Py_file_input);
       
    68 	PyEval_EvalCode(code, globals, locals);
       
    69 	Py_DECREF(code);
       
    70 	Py_DECREF(locals);
       
    71 	Py_DECREF(mtext);
       
    72 	Py_Finalize();
       
    73 	return 0; // Non-zero return values are reserved for future use.
       
    74 }
       
    75 }