8000 Add a fuzz target for `_elementtree.XMLParser._parse_whole` by bradlarsen · Pull Request #111477 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

Add a fuzz target for _elementtree.XMLParser._parse_whole #111477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 3, 2023
Next Next commit
Add a fuzzer for _elementtree.XMLParser._parse_whole
  • Loading branch information
bradlarsen committed Oct 29, 2023
commit ae96a12a67733de55b73b82d4628b41f5465b671
1 change: 1 addition & 0 deletions Modules/_xxtestfuzz/fuzz_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ fuzz_sre_match
fuzz_csv_reader
fuzz_struct_unpack
fuzz_ast_literal_eval
fuzz_elementtree_parsewhole
73 changes: 73 additions & 0 deletions Modules/_xxtestfuzz/fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,68 @@ static int fuzz_ast_literal_eval(const char* data, size_t size) {
return 0;
}

#define MAX_ELEMENTTREE_PARSEWHOLE_TEST_SIZE 0x100000
PyObject* xml_parser_type = NULL;
PyObject* bytesio_type = NULL;
/* Called by LLVMFuzzerTestOneInput for initialization */
static int init_elementtree_parsewhole(void) {
PyObject* elementtree_module = PyImport_ImportModule("_elementtree");
if (elementtree_module == NULL) {
return 0;
}
xml_parser_type = PyObject_GetAttrString(elementtree_module, "XMLParser");
if (xml_parser_type == NULL) {
return 0;
}
Py_DECREF(elementtree_module);


PyObject* io_module = PyImport_ImportModule("io");
if (io_module == NULL) {
return 0;
}
bytesio_type = PyObject_GetAttrString(io_module, "BytesIO");
if (bytesio_type == NULL) {
return 0;
}
Py_DECREF(io_module);

return 1;
}
/* Fuzz _elementtree.XMLParser._parse_whole(x) */
static int fuzz_elementtree_parsewhole(const char* data, size_t size) {
if (size > MAX_ELEMENTTREE_PARSEWHOLE_TEST_SIZE) {
return 0;
}

PyObject *input = PyObject_CallFunction(bytesio_type, "y#", data, (Py_ssize_t)size);
if (input == NULL) {
assert(PyErr_Occurred());
PyErr_Print();
abort();
}

PyObject *xmlparser_instance = PyObject_CallObject(xml_parser_type, NULL);
if (xmlparser_instance == NULL) {
assert(PyErr_Occurred());
PyErr_Print();
abort();
}

PyObject *result = PyObject_CallMethod(xmlparser_instance, "_parse_whole", "O", input);
if (result == NULL) {
/* Ignore exception here, which can be caused by invalid XML input */
PyErr_Clear();
} else {
Py_DECREF(result);
}

Py_DECREF(xmlparser_instance);
Py_DECREF(input);

return 0;
}

/* Run fuzzer and abort on failure. */
static int _run_fuzz(const uint8_t *data, size_t size, int(*fuzzer)(const char* , size_t)) {
int rv = fuzzer((const char*) data, size);
Expand Down Expand Up @@ -569,6 +631,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}

rv |= _run_fuzz(data, size, fuzz_ast_literal_eval);
#endif
#if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_fuzz_elementtree_parsewhole)
static int ELEMENTTREE_PARSEWHOLE_INITIALIZED = 0;
if (!ELEMENTTREE_PARSEWHOLE_INITIALIZED && !init_elementtree_parsewhole()) {
PyErr_Print();
abort();
} else {
ELEMENTTREE_PARSEWHOLE_INITIALIZED = 1;
}

rv |= _run_fuzz(data, size, fuzz_elementtree_parsewhole);
#endif
return rv;
}
0