Skip to content

Commit d25d2d6

Browse files
authored
[3.13] pythongh-116946: fully implement GC protocol for zlib objects (pythonGH-138290) (python#138328)
(cherry picked from commit 2a54acf)
1 parent 21b5932 commit d25d2d6

File tree

1 file changed

+61
-19
lines changed

1 file changed

+61
-19
lines changed

Modules/zlibmodule.c

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ typedef struct
221221
PyThread_type_lock lock;
222222
} compobject;
223223

224+
#define _compobject_CAST(op) ((compobject *)op)
225+
224226
static void
225227
zlib_error(zlibstate *state, z_stream zst, int err, const char *msg)
226228
{
@@ -261,7 +263,9 @@ static compobject *
261263
newcompobject(PyTypeObject *type)
262264
{
263265
compobject *self;
264-
self = PyObject_New(compobject, type);
266+
assert(type != NULL);
267+
assert(type->tp_alloc != NULL);
268+
self = _compobject_CAST(type->tp_alloc(type, 0));
265269
if (self == NULL)
266270
return NULL;
267271
self->eof = 0;
@@ -704,31 +708,41 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
704708
}
705709

706710
static void
707-
Dealloc(compobject *self)
711+
compobject_dealloc_impl(PyObject *op, int (*dealloc)(z_streamp))
708712
{
709-
PyObject *type = (PyObject *)Py_TYPE(self);
713+
PyTypeObject *type = Py_TYPE(op);
714+
PyObject_GC_UnTrack(op);
715+
compobject *self = _compobject_CAST(op);
716+
if (self->is_initialised) {
717+
(void)dealloc(&self->zst);
718+
}
710719
PyThread_free_lock(self->lock);
711720
Py_XDECREF(self->unused_data);
712721
Py_XDECREF(self->unconsumed_tail);
713722
Py_XDECREF(self->zdict);
714-
PyObject_Free(self);
723+
type->tp_free(self);
715724
Py_DECREF(type);
716725
}
717726

727+
static int
728+
compobject_traverse(PyObject *op, visitproc visit, void *arg)
729+
{
730+
compobject *self = _compobject_CAST(op);
731+
Py_VISIT(Py_TYPE(op));
732+
Py_VISIT(self->zdict);
733+
return 0;
734+
}
735+
718736
static void
719-
Comp_dealloc(compobject *self)
737+
Comp_dealloc(PyObject *op)
720738
{
721-
if (self->is_initialised)
722-
deflateEnd(&self->zst);
723-
Dealloc(self);
739+
compobject_dealloc_impl(op, &deflateEnd);
724740
}
725741

726742
static void
727-
Decomp_dealloc(compobject *self)
743+
Decomp_dealloc(PyObject *op)
728744
{
729-
if (self->is_initialised)
730-
inflateEnd(&self->zst);
731-
Dealloc(self);
745+
compobject_dealloc_impl(op, &inflateEnd);
732746
}
733747

734748
/*[clinic input]
@@ -1353,26 +1367,39 @@ typedef struct {
13531367
char needs_input;
13541368
} ZlibDecompressor;
13551369

1370+
#define ZlibDecompressor_CAST(op) ((ZlibDecompressor *)(op))
1371+
13561372
/*[clinic input]
13571373
class zlib.ZlibDecompressor "ZlibDecompressor *" "&ZlibDecompressorType"
13581374
[clinic start generated code]*/
13591375
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=0658178ab94645df]*/
13601376

13611377
static void
1362-
ZlibDecompressor_dealloc(ZlibDecompressor *self)
1378+
ZlibDecompressor_dealloc(PyObject *op)
13631379
{
1364-
PyObject *type = (PyObject *)Py_TYPE(self);
1380+
PyTypeObject *type = Py_TYPE(op);
1381+
PyObject_GC_UnTrack(op);
1382+
ZlibDecompressor *self = ZlibDecompressor_CAST(op);
13651383
PyThread_free_lock(self->lock);
13661384
if (self->is_initialised) {
13671385
inflateEnd(&self->zst);
13681386
}
13691387
PyMem_Free(self->input_buffer);
13701388
Py_CLEAR(self->unused_data);
13711389
Py_CLEAR(self->zdict);
1372-
PyObject_Free(self);
1390+
type->tp_free(self);
13731391
Py_DECREF(type);
13741392
}
13751393

1394+
static int
1395+
ZlibDecompressor_traverse(PyObject *op, visitproc visit, void *arg)
1396+
{
1397+
ZlibDecompressor *self = ZlibDecompressor_CAST(op);
1398+
Py_VISIT(Py_TYPE(op));
1399+
Py_VISIT(self->zdict);
1400+
return 0;
1401+
}
1402+
13761403
static int
13771404
set_inflate_zdict_ZlibDecompressor(zlibstate *state, ZlibDecompressor *self)
13781405
{
@@ -1724,7 +1751,7 @@ ZlibDecompressor__new__(PyTypeObject *cls,
17241751
args, kwargs, format, keywords, &wbits, &zdict)) {
17251752
return NULL;
17261753
}
1727-
ZlibDecompressor *self = PyObject_New(ZlibDecompressor, cls);
1754+
ZlibDecompressor *self = ZlibDecompressor_CAST(cls->tp_alloc(cls, 0));
17281755
if (self == NULL) {
17291756
return NULL;
17301757
}
@@ -1932,19 +1959,25 @@ static PyMethodDef zlib_methods[] =
19321959

19331960
static PyType_Slot Comptype_slots[] = {
19341961
{Py_tp_dealloc, Comp_dealloc},
1962+
{Py_tp_traverse, compobject_traverse},
19351963
{Py_tp_methods, comp_methods},
19361964
{0, 0},
19371965
};
19381966

19391967
static PyType_Spec Comptype_spec = {
19401968
.name = "zlib.Compress",
19411969
.basicsize = sizeof(compobject),
1942-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
1970+
.flags = (
1971+
Py_TPFLAGS_DEFAULT
1972+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
1973+
| Py_TPFLAGS_HAVE_GC
1974+
),
19431975
.slots= Comptype_slots,
19441976
};
19451977

19461978
static PyType_Slot Decomptype_slots[] = {
19471979
{Py_tp_dealloc, Decomp_dealloc},
1980+
{Py_tp_traverse, compobject_traverse},
19481981
{Py_tp_methods, Decomp_methods},
19491982
{Py_tp_members, Decomp_members},
19501983
{0, 0},
@@ -1953,12 +1986,17 @@ static PyType_Slot Decomptype_slots[] = {
19531986
static PyType_Spec Decomptype_spec = {
19541987
.name = "zlib.Decompress",
19551988
.basicsize = sizeof(compobject),
1956-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
1989+
.flags = (
1990+
Py_TPFLAGS_DEFAULT
1991+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
1992+
| Py_TPFLAGS_HAVE_GC
1993+
),
19571994
.slots = Decomptype_slots,
19581995
};
19591996

19601997
static PyType_Slot ZlibDecompressor_type_slots[] = {
19611998
{Py_tp_dealloc, ZlibDecompressor_dealloc},
1999+
{Py_tp_traverse, ZlibDecompressor_traverse},
19622000
{Py_tp_members, ZlibDecompressor_members},
19632001
{Py_tp_new, ZlibDecompressor__new__},
19642002
{Py_tp_doc, (char *)ZlibDecompressor__new____doc__},
@@ -1973,7 +2011,11 @@ static PyType_Spec ZlibDecompressor_type_spec = {
19732011
// ZlibDecompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag
19742012
// which prevents to create a subclass.
19752013
// So calling PyType_GetModuleState() in this file is always safe.
1976-
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE),
2014+
.flags = (
2015+
Py_TPFLAGS_DEFAULT
2016+
| Py_TPFLAGS_IMMUTABLETYPE
2017+
| Py_TPFLAGS_HAVE_GC
2018+
),
19772019
.slots = ZlibDecompressor_type_slots,
19782020
};
19792021
PyDoc_STRVAR(zlib_module_documentation,

0 commit comments

Comments
 (0)