summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2020-04-27 14:24:31 (GMT)
committerGitHub <noreply@github.com>2020-04-27 14:24:31 (GMT)
commit91a5ae18351027867e99c96db5ea235d9c42e47a (patch)
tree059fcf1982a6bfa6fbc751a064571c1e8a4bf03d
parent0169d3003be3d072751dd14a5c84748ab63a249f (diff)
downloadcpython-91a5ae18351027867e99c96db5ea235d9c42e47a.zip
cpython-91a5ae18351027867e99c96db5ea235d9c42e47a.tar.gz
cpython-91a5ae18351027867e99c96db5ea235d9c42e47a.tar.bz2
bpo-40217: Clean code in PyType_FromSpec_Alloc and add NEWS entry (GH-19733)
-rw-r--r--Misc/NEWS.d/next/C API/2020-04-27-14-00-38.bpo-40217.sgn6c8.rst5
-rw-r--r--Objects/typeobject.c26
2 files changed, 22 insertions, 9 deletions
diff --git a/Misc/NEWS.d/next/C API/2020-04-27-14-00-38.bpo-40217.sgn6c8.rst b/Misc/NEWS.d/next/C API/2020-04-27-14-00-38.bpo-40217.sgn6c8.rst
new file mode 100644
index 0000000..72df4a7
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2020-04-27-14-00-38.bpo-40217.sgn6c8.rst
@@ -0,0 +1,5 @@
+Ensure that instances of types created with
+:c:func:`PyType_FromSpecWithBases` will visit its class object when
+traversing references in the garbage collector (implemented as an extension
+of the provided :c:member:`~PyTypeObject.tp_traverse`). Patch by Pablo
+Galindo.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 6a9bd70..bf95dd6 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1031,25 +1031,29 @@ PyType_FromSpec_Alloc(PyTypeObject *type, Py_ssize_t nitems)
/* note that we need to add one, for the sentinel and space for the
provided tp-traverse: See bpo-40217 for more details */
- if (PyType_IS_GC(type))
+ if (PyType_IS_GC(type)) {
obj = _PyObject_GC_Malloc(size);
- else
+ }
+ else {
obj = (PyObject *)PyObject_MALLOC(size);
+ }
- if (obj == NULL)
+ if (obj == NULL) {
return PyErr_NoMemory();
-
- obj = obj;
+ }
memset(obj, '\0', size);
- if (type->tp_itemsize == 0)
+ if (type->tp_itemsize == 0) {
(void)PyObject_INIT(obj, type);
- else
+ }
+ else {
(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);
+ }
- if (PyType_IS_GC(type))
+ if (PyType_IS_GC(type)) {
_PyObject_GC_TRACK(obj);
+ }
return obj;
}
@@ -3066,7 +3070,11 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
*
* We store the user-provided traverse function at the end of the type
* (we have allocated space for it) so we can call it from our
- * PyType_FromSpec_tp_traverse wrapper. */
+ * PyType_FromSpec_tp_traverse wrapper.
+ *
+ * Check bpo-40217 for more information and rationale about this issue.
+ *
+ * */
type->tp_traverse = PyType_FromSpec_tp_traverse;
size_t _offset = _PyObject_VAR_SIZE(&PyType_Type, nmembers+1);