From 4300352000beed22fb525ec45fd331918d206528 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 31 Aug 2021 18:05:15 +0200 Subject: [PATCH] bpo-45061: Detect Py_DECREF(Py_True) bug (GH-28089) Add a deallocator to the bool type to detect refcount bugs in C extensions which call Py_DECREF(Py_True) or Py_DECREF(Py_False) by mistake. --- .../next/C API/2021-08-31-15-21-36.bpo-45061.ZH0HVe.rst | 3 +++ Objects/boolobject.c | 9 ++++++++- Objects/object.c | 9 +++------ 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2021-08-31-15-21-36.bpo-45061.ZH0HVe.rst diff --git a/Misc/NEWS.d/next/C API/2021-08-31-15-21-36.bpo-45061.ZH0HVe.rst b/Misc/NEWS.d/next/C API/2021-08-31-15-21-36.bpo-45061.ZH0HVe.rst new file mode 100644 index 00000000000..58bd534601f --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-08-31-15-21-36.bpo-45061.ZH0HVe.rst @@ -0,0 +1,3 @@ +Add a deallocator to the :class:`bool` type to detect refcount bugs in C +extensions which call ``Py_DECREF(Py_True);`` or ``Py_DECREF(Py_False);`` by +mistake. Patch by Victor Stinner. diff --git a/Objects/boolobject.c b/Objects/boolobject.c index b786966533e..bc1666f5571 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -153,6 +153,13 @@ static PyNumberMethods bool_as_number = { 0, /* nb_index */ }; +static void _Py_NO_RETURN +bool_dealloc(PyObject* Py_UNUSED(ignore)) +{ + Py_FatalError("deallocating True or False likely caused by " + "a refcount bug in a C extension"); +} + /* The type object for bool. Note that this cannot be subclassed! */ PyTypeObject PyBool_Type = { @@ -160,7 +167,7 @@ PyTypeObject PyBool_Type = { "bool", sizeof(struct _longobject), 0, - 0, /* tp_dealloc */ + bool_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ diff --git a/Objects/object.c b/Objects/object.c index 446c974f8e6..026262b5448 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1560,14 +1560,11 @@ none_repr(PyObject *op) return PyUnicode_FromString("None"); } -/* ARGUSED */ static void _Py_NO_RETURN -none_dealloc(PyObject* ignore) +none_dealloc(PyObject* Py_UNUSED(ignore)) { - /* This should never get called, but we also don't want to SEGV if - * we accidentally decref None out of existence. - */ - Py_FatalError("deallocating None"); + Py_FatalError("deallocating None likely caused by a refcount bug " + "in a C extension"); } static PyObject *