bpo-40217: Ensure Py_VISIT(Py_TYPE(self)) is always called for PyTyp… · python/cpython@1cf15af (original) (raw)

`@@ -1039,42 +1039,6 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)

`

1039

1039

`return obj;

`

1040

1040

`}

`

1041

1041

``

1042

``

`-

PyObject *

`

1043

``

`-

PyType_FromSpec_Alloc(PyTypeObject *type, Py_ssize_t nitems)

`

1044

``

`-

{

`

1045

``

`-

PyObject *obj;

`

1046

``

`-

const size_t size = _Py_SIZE_ROUND_UP(

`

1047

``

`-

_PyObject_VAR_SIZE(type, nitems+1) + sizeof(traverseproc),

`

1048

``

`-

SIZEOF_VOID_P);

`

1049

``

`-

/* note that we need to add one, for the sentinel and space for the

`

1050

``

`-

provided tp-traverse: See bpo-40217 for more details */

`

1051

``

-

1052

``

`-

if (PyType_IS_GC(type)) {

`

1053

``

`-

obj = _PyObject_GC_Malloc(size);

`

1054

``

`-

}

`

1055

``

`-

else {

`

1056

``

`-

obj = (PyObject *)PyObject_MALLOC(size);

`

1057

``

`-

}

`

1058

``

-

1059

``

`-

if (obj == NULL) {

`

1060

``

`-

return PyErr_NoMemory();

`

1061

``

`-

}

`

1062

``

-

1063

``

`-

memset(obj, '\0', size);

`

1064

``

-

1065

``

`-

if (type->tp_itemsize == 0) {

`

1066

``

`-

(void)PyObject_INIT(obj, type);

`

1067

``

`-

}

`

1068

``

`-

else {

`

1069

``

`-

(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);

`

1070

``

`-

}

`

1071

``

-

1072

``

`-

if (PyType_IS_GC(type)) {

`

1073

``

`-

_PyObject_GC_TRACK(obj);

`

1074

``

`-

}

`

1075

``

`-

return obj;

`

1076

``

`-

}

`

1077

``

-

1078

1042

`PyObject *

`

1079

1043

`PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)

`

1080

1044

`{

`

`@@ -1164,11 +1128,16 @@ subtype_traverse(PyObject *self, visitproc visit, void *arg)

`

1164

1128

`Py_VISIT(*dictptr);

`

1165

1129

` }

`

1166

1130

``

1167

``

`-

if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)

`

``

1131

`+

if (type->tp_flags & Py_TPFLAGS_HEAPTYPE

`

``

1132

`+

&& (!basetraverse || !(base->tp_flags & Py_TPFLAGS_HEAPTYPE))) {

`

1168

1133

`/* For a heaptype, the instances count as references

`

1169

1134

` to the type. Traverse the type so the collector

`

1170

``

`-

can find cycles involving this link. */

`

``

1135

`+

can find cycles involving this link.

`

``

1136

`+

Skip this visit if basetraverse belongs to a heap type: in that

`

``

1137

`+

case, basetraverse will visit the type when we call it later.

`

``

1138

`+

*/

`

1171

1139

`Py_VISIT(type);

`

``

1140

`+

}

`

1172

1141

``

1173

1142

`if (basetraverse)

`

1174

1143

`return basetraverse(self, visit, arg);

`

`@@ -2910,36 +2879,6 @@ static const short slotoffsets[] = {

`

2910

2879

`#include "typeslots.inc"

`

2911

2880

`};

`

2912

2881

``

2913

``

`-

static int

`

2914

``

`-

PyType_FromSpec_tp_traverse(PyObject *self, visitproc visit, void *arg)

`

2915

``

`-

{

`

2916

``

`-

PyTypeObject *parent = Py_TYPE(self);

`

2917

``

-

2918

``

`-

// Only a instance of a type that is directly created by

`

2919

``

`-

// PyType_FromSpec (not subclasses) must visit its parent.

`

2920

``

`-

if (parent->tp_traverse == PyType_FromSpec_tp_traverse) {

`

2921

``

`-

Py_VISIT(parent);

`

2922

``

`-

}

`

2923

``

-

2924

``

`-

// Search for the original type that was created using PyType_FromSpec

`

2925

``

`-

PyTypeObject *base;

`

2926

``

`-

base = parent;

`

2927

``

`-

while (base->tp_traverse != PyType_FromSpec_tp_traverse) {

`

2928

``

`-

base = base->tp_base;

`

2929

``

`-

assert(base);

`

2930

``

`-

}

`

2931

``

-

2932

``

`-

// Extract the user defined traverse function that we placed at the end

`

2933

``

`-

// of the type and call it.

`

2934

``

`-

size_t size = Py_SIZE(base);

`

2935

``

`-

size_t _offset = _PyObject_VAR_SIZE(&PyType_Type, size+1);

`

2936

``

`-

traverseproc fun = (traverseproc)((char*)base + _offset);

`

2937

``

`-

if (fun == NULL) {

`

2938

``

`-

return 0;

`

2939

``

`-

}

`

2940

``

`-

return fun(self, visit, arg);

`

2941

``

`-

}

`

2942

``

-

2943

2882

`PyObject *

`

2944

2883

`PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)

`

2945

2884

`{

`

`@@ -2985,7 +2924,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)

`

2985

2924

` }

`

2986

2925

` }

`

2987

2926

``

2988

``

`-

res = (PyHeapTypeObject*)PyType_FromSpec_Alloc(&PyType_Type, nmembers);

`

``

2927

`+

res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, nmembers);

`

2989

2928

`if (res == NULL)

`

2990

2929

`return NULL;

`

2991

2930

`res_start = (char*)res;

`

`@@ -3093,30 +3032,6 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)

`

3093

3032

`memcpy(PyHeapType_GET_MEMBERS(res), slot->pfunc, len);

`

3094

3033

`type->tp_members = PyHeapType_GET_MEMBERS(res);

`

3095

3034

` }

`

3096

``

`-

else if (slot->slot == Py_tp_traverse) {

`

3097

``

-

3098

``

`-

/* Types created by PyType_FromSpec own a strong reference to their

`

3099

``

`-

`

3100

``

`-

`

3101

``

`-

`

3102

``

`-

`

3103

``

`-

`

3104

``

`-

`

3105

``

`-

`

3106

``

`-

`

3107

``

`-

`

3108

``

`-

`

3109

``

`-

`

3110

``

`-

`

3111

``

`-

`

3112

``

`-

`

3113

``

`-

`

3114

``

-

3115

``

`-

type->tp_traverse = PyType_FromSpec_tp_traverse;

`

3116

``

`-

size_t _offset = _PyObject_VAR_SIZE(&PyType_Type, nmembers+1);

`

3117

``

`-

traverseproc user_traverse = (traverseproc)((char*)type + _offset);

`

3118

``

`-

*user_traverse = slot->pfunc;

`

3119

``

`-

}

`

3120

3035

`else {

`

3121

3036

`/* Copy other slots directly */

`

3122

3037

`(void*)(res_start + slotoffsets[slot->slot]) = slot->pfunc;

`