diff options
author | Victor Stinner <vstinner@python.org> | 2023-09-18 14:59:09 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-18 14:59:09 (GMT) |
commit | 0bb0d88e2d4e300946e399e088e2ff60de2ccf8c (patch) | |
tree | e197a96bdf8c45937a2f839fd723a9bb58270c47 /Modules | |
parent | ef659b96169888e52b6ff03ce28fffaaa8f76818 (diff) | |
download | cpython-0bb0d88e2d4e300946e399e088e2ff60de2ccf8c.zip cpython-0bb0d88e2d4e300946e399e088e2ff60de2ccf8c.tar.gz cpython-0bb0d88e2d4e300946e399e088e2ff60de2ccf8c.tar.bz2 |
gh-109496: Detect Py_DECREF() after dealloc in debug mode (#109539)
On a Python built in debug mode, Py_DECREF() now calls
_Py_NegativeRefcount() if the object is a dangling pointer to
deallocated memory: memory filled with 0xDD "dead byte" by the debug
hook on memory allocators. The fix is to check the reference count
*before* checking for _Py_IsImmortal().
Add test_decref_freed_object() to test_capi.test_misc.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_testcapimodule.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 85d8401..f356fc5 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2034,6 +2034,26 @@ negative_refcount(PyObject *self, PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } + +static PyObject * +decref_freed_object(PyObject *self, PyObject *Py_UNUSED(args)) +{ + PyObject *obj = PyUnicode_FromString("decref_freed_object"); + if (obj == NULL) { + return NULL; + } + assert(Py_REFCNT(obj) == 1); + + // Deallocate the memory + Py_DECREF(obj); + // obj is a now a dangling pointer + + // gh-109496: If Python is built in debug mode, Py_DECREF() must call + // _Py_NegativeRefcount() and abort Python. + Py_DECREF(obj); + + Py_RETURN_NONE; +} #endif @@ -3299,6 +3319,7 @@ static PyMethodDef TestMethods[] = { {"bad_get", _PyCFunction_CAST(bad_get), METH_FASTCALL}, #ifdef Py_REF_DEBUG {"negative_refcount", negative_refcount, METH_NOARGS}, + {"decref_freed_object", decref_freed_object, METH_NOARGS}, #endif {"meth_varargs", meth_varargs, METH_VARARGS}, {"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS}, |