diff --git a/Lib/test/test_capi/test_getargs.py b/Lib/test/test_capi/test_getargs.py index 72b6d64a49863a..552fa213524723 100644 --- a/Lib/test/test_capi/test_getargs.py +++ b/Lib/test/test_capi/test_getargs.py @@ -1098,6 +1098,10 @@ def test_Z_hash(self): warnings.simplefilter('error', DeprecationWarning) self.assertRaises(DeprecationWarning, getargs_Z_hash, 'abc\xe9') + def test_gh_99240_clear_args(self): + from _testcapi import gh_99240_clear_args + self.assertRaises(TypeError, gh_99240_clear_args, 'a', '\0b') + class Object_TestCase(unittest.TestCase): def test_S(self): diff --git a/Misc/NEWS.d/next/C API/2022-11-30-16-39-22.gh-issue-99240.67nAX-.rst b/Misc/NEWS.d/next/C API/2022-11-30-16-39-22.gh-issue-99240.67nAX-.rst new file mode 100644 index 00000000000000..9a1bb3cf5a73f0 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-11-30-16-39-22.gh-issue-99240.67nAX-.rst @@ -0,0 +1,2 @@ +In argument parsing, after deallocating newly allocated memory, reset its +pointer to NULL. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 1291eff481cbb8..70242d78ab8c54 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -6192,6 +6192,7 @@ function_get_module(PyObject *self, PyObject *func) static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*); static PyObject *getargs_s_hash_int2(PyObject *, PyObject *, PyObject*); +static PyObject *gh_99240_clear_args(PyObject *, PyObject *); static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -6308,6 +6309,7 @@ static PyMethodDef TestMethods[] = { METH_VARARGS|METH_KEYWORDS}, {"getargs_s_hash_int2", _PyCFunction_CAST(getargs_s_hash_int2), METH_VARARGS|METH_KEYWORDS}, + {"gh_99240_clear_args", gh_99240_clear_args, METH_VARARGS}, {"getargs_z", getargs_z, METH_VARARGS}, {"getargs_z_star", getargs_z_star, METH_VARARGS}, {"getargs_z_hash", getargs_z_hash, METH_VARARGS}, @@ -8089,3 +8091,21 @@ getargs_s_hash_int2(PyObject *self, PyObject *args, PyObject *kwargs) PyBuffer_Release(&buf); Py_RETURN_NONE; } + +static PyObject * +gh_99240_clear_args(PyObject *self, PyObject *args) +{ + char *a = NULL; + char *b = NULL; + + if (!PyArg_ParseTuple(args, "eses", "idna", &a, "idna", &b)) { + if (a || b) { + PyErr_Clear(); + PyErr_SetString(PyExc_AssertionError, "Arguments are not cleared."); + } + return NULL; + } + PyMem_Free(a); + PyMem_Free(b); + Py_RETURN_NONE; +} diff --git a/Python/getargs.c b/Python/getargs.c index c3e3cf155b870a..9d6483f4fe0f7c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -202,9 +202,9 @@ _PyArg_VaParse_SizeT(PyObject *args, const char *format, va_list va) static int cleanup_ptr(PyObject *self, void *ptr) { - if (ptr) { - PyMem_Free(ptr); - } + void **pptr = (void **)ptr; + PyMem_Free(*pptr); + *pptr = NULL; return 0; } @@ -1169,7 +1169,7 @@ _Py_COMP_DIAG_POP PyErr_NoMemory(); RETURN_ERR_OCCURRED; } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr( "(cleanup problem)", @@ -1215,7 +1215,7 @@ _Py_COMP_DIAG_POP PyErr_NoMemory(); RETURN_ERR_OCCURRED; } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize);