Skip to content

Commit

Permalink
Add PoC of pythonGH-99240
Browse files Browse the repository at this point in the history
  • Loading branch information
colorfulappl committed Nov 8, 2022
1 parent 10ce3c7 commit 2cc6c0a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
7 changes: 6 additions & 1 deletion Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ def test_str_converter_encoding(self):
with self.assertRaises(TypeError):
ac_tester.str_converter_encoding(1)
self.assertEqual(ac_tester.str_converter_encoding('a', 'b', 'c'), ('a', 'b', 'c'))
with self.assertRaises(ValueError):
with self.assertRaises(TypeError):
ac_tester.str_converter_encoding('a', b'b\0b', 'c')
self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c')])), ('a', 'b', 'c'))
self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c'), 0, ord('c')])),
Expand Down Expand Up @@ -1263,5 +1263,10 @@ def test_gh_99233_refcount(self):
arg_refcount_after = sys.getrefcount(arg)
self.assertEqual(arg_refcount_origin, arg_refcount_after)

def test_gh_99240_double_free(self):
expected_error = r'gh_99240_double_free\(\) argument 2 must be encoded string without null bytes, not str'
with self.assertRaisesRegex(TypeError, expected_error):
ac_tester.gh_99240_double_free('a', '\0b')

if __name__ == "__main__":
unittest.main()
29 changes: 29 additions & 0 deletions Modules/_testclinic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,34 @@ gh_99233_refcount_impl(PyObject *module, PyObject *args)
}


/*[clinic input]
gh_99240_double_free
a: str(encoding="idna")
b: str(encoding="idna")
/
Proof-of-concept of GH-99240 double-free bug.
If parsing `a` successes, `a` will be assigned an address points to an allocated memory.
After that, if parsing `b` fails, the memory which `a` points to is freed by function `_PyArg_ParseStack`,
and `_PyArg_ParseStack` returns 0, then control flow goes to label "exit".
At this time, `a` is not NULL, so the memory it points to is freed again,
which cause a double-free problem and a runtime crash.
Calling this function by gh_99240_double_free('a', '\0b')
to trigger this bug (crash).
[clinic start generated code]*/

static PyObject *
gh_99240_double_free_impl(PyObject *module, char *a, char *b)
/*[clinic end generated code: output=586dc714992fe2ed input=419d3a3790de435e]*/
{
Py_RETURN_NONE;
}


static PyMethodDef tester_methods[] = {
TEST_EMPTY_FUNCTION_METHODDEF
OBJECTS_CONVERTER_METHODDEF
Expand Down Expand Up @@ -1101,6 +1129,7 @@ static PyMethodDef tester_methods[] = {
GH_32092_OOB_METHODDEF
GH_32092_KW_PASS_METHODDEF
GH_99233_REFCOUNT_METHODDEF
GH_99240_DOUBLE_FREE_METHODDEF
{NULL, NULL}
};

Expand Down
49 changes: 48 additions & 1 deletion Modules/clinic/_testclinic.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2cc6c0a

Please sign in to comment.