gh-116946: fully implement GC protocol for zlib objects (#138290)

This commit is contained in:
Bénédikt Tran 2025-09-01 10:24:23 +02:00 committed by GitHub
parent 6f1dd9551a
commit 2a54acf3c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -273,7 +273,9 @@ static compobject *
newcompobject(PyTypeObject *type) newcompobject(PyTypeObject *type)
{ {
compobject *self; compobject *self;
self = PyObject_New(compobject, type); assert(type != NULL);
assert(type->tp_alloc != NULL);
self = _compobject_CAST(type->tp_alloc(type, 0));
if (self == NULL) if (self == NULL)
return NULL; return NULL;
self->eof = 0; self->eof = 0;
@ -716,33 +718,41 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
} }
static void static void
Dealloc(compobject *self) compobject_dealloc_impl(PyObject *op, int (*dealloc)(z_streamp))
{ {
PyTypeObject *type = Py_TYPE(self); PyTypeObject *type = Py_TYPE(op);
PyObject_GC_UnTrack(op);
compobject *self = _compobject_CAST(op);
if (self->is_initialised) {
(void)dealloc(&self->zst);
}
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
Py_XDECREF(self->unused_data); Py_XDECREF(self->unused_data);
Py_XDECREF(self->unconsumed_tail); Py_XDECREF(self->unconsumed_tail);
Py_XDECREF(self->zdict); Py_XDECREF(self->zdict);
PyObject_Free(self); type->tp_free(self);
Py_DECREF(type); Py_DECREF(type);
} }
static int
compobject_traverse(PyObject *op, visitproc visit, void *arg)
{
compobject *self = _compobject_CAST(op);
Py_VISIT(Py_TYPE(op));
Py_VISIT(self->zdict);
return 0;
}
static void static void
Comp_dealloc(PyObject *op) Comp_dealloc(PyObject *op)
{ {
compobject *self = _compobject_CAST(op); compobject_dealloc_impl(op, &deflateEnd);
if (self->is_initialised)
(void)deflateEnd(&self->zst);
Dealloc(self);
} }
static void static void
Decomp_dealloc(PyObject *op) Decomp_dealloc(PyObject *op)
{ {
compobject *self = _compobject_CAST(op); compobject_dealloc_impl(op, &inflateEnd);
if (self->is_initialised)
(void)inflateEnd(&self->zst);
Dealloc(self);
} }
/*[clinic input] /*[clinic input]
@ -1368,6 +1378,8 @@ typedef struct {
char needs_input; char needs_input;
} ZlibDecompressor; } ZlibDecompressor;
#define ZlibDecompressor_CAST(op) ((ZlibDecompressor *)(op))
/*[clinic input] /*[clinic input]
class zlib._ZlibDecompressor "ZlibDecompressor *" "&ZlibDecompressorType" class zlib._ZlibDecompressor "ZlibDecompressor *" "&ZlibDecompressorType"
[clinic start generated code]*/ [clinic start generated code]*/
@ -1376,8 +1388,9 @@ class zlib._ZlibDecompressor "ZlibDecompressor *" "&ZlibDecompressorType"
static void static void
ZlibDecompressor_dealloc(PyObject *op) ZlibDecompressor_dealloc(PyObject *op)
{ {
ZlibDecompressor *self = (ZlibDecompressor*)op; PyTypeObject *type = Py_TYPE(op);
PyObject *type = (PyObject *)Py_TYPE(self); PyObject_GC_UnTrack(op);
ZlibDecompressor *self = ZlibDecompressor_CAST(op);
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
if (self->is_initialised) { if (self->is_initialised) {
inflateEnd(&self->zst); inflateEnd(&self->zst);
@ -1385,10 +1398,19 @@ ZlibDecompressor_dealloc(PyObject *op)
PyMem_Free(self->input_buffer); PyMem_Free(self->input_buffer);
Py_CLEAR(self->unused_data); Py_CLEAR(self->unused_data);
Py_CLEAR(self->zdict); Py_CLEAR(self->zdict);
PyObject_Free(self); type->tp_free(self);
Py_DECREF(type); Py_DECREF(type);
} }
static int
ZlibDecompressor_traverse(PyObject *op, visitproc visit, void *arg)
{
ZlibDecompressor *self = ZlibDecompressor_CAST(op);
Py_VISIT(Py_TYPE(op));
Py_VISIT(self->zdict);
return 0;
}
static int static int
set_inflate_zdict_ZlibDecompressor(zlibstate *state, ZlibDecompressor *self) set_inflate_zdict_ZlibDecompressor(zlibstate *state, ZlibDecompressor *self)
{ {
@ -1731,8 +1753,9 @@ static PyObject *
zlib__ZlibDecompressor_impl(PyTypeObject *type, int wbits, PyObject *zdict) zlib__ZlibDecompressor_impl(PyTypeObject *type, int wbits, PyObject *zdict)
/*[clinic end generated code: output=1065607df0d33baa input=9ebad0be6de226e2]*/ /*[clinic end generated code: output=1065607df0d33baa input=9ebad0be6de226e2]*/
{ {
assert(type != NULL && type->tp_alloc != NULL);
zlibstate *state = PyType_GetModuleState(type); zlibstate *state = PyType_GetModuleState(type);
ZlibDecompressor *self = PyObject_New(ZlibDecompressor, type); ZlibDecompressor *self = ZlibDecompressor_CAST(type->tp_alloc(type, 0));
if (self == NULL) { if (self == NULL) {
return NULL; return NULL;
} }
@ -2015,6 +2038,7 @@ static PyMethodDef zlib_methods[] =
static PyType_Slot Comptype_slots[] = { static PyType_Slot Comptype_slots[] = {
{Py_tp_dealloc, Comp_dealloc}, {Py_tp_dealloc, Comp_dealloc},
{Py_tp_traverse, compobject_traverse},
{Py_tp_methods, comp_methods}, {Py_tp_methods, comp_methods},
{0, 0}, {0, 0},
}; };
@ -2022,12 +2046,17 @@ static PyType_Slot Comptype_slots[] = {
static PyType_Spec Comptype_spec = { static PyType_Spec Comptype_spec = {
.name = "zlib.Compress", .name = "zlib.Compress",
.basicsize = sizeof(compobject), .basicsize = sizeof(compobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, .flags = (
Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_DISALLOW_INSTANTIATION
| Py_TPFLAGS_HAVE_GC
),
.slots= Comptype_slots, .slots= Comptype_slots,
}; };
static PyType_Slot Decomptype_slots[] = { static PyType_Slot Decomptype_slots[] = {
{Py_tp_dealloc, Decomp_dealloc}, {Py_tp_dealloc, Decomp_dealloc},
{Py_tp_traverse, compobject_traverse},
{Py_tp_methods, Decomp_methods}, {Py_tp_methods, Decomp_methods},
{Py_tp_members, Decomp_members}, {Py_tp_members, Decomp_members},
{0, 0}, {0, 0},
@ -2036,12 +2065,17 @@ static PyType_Slot Decomptype_slots[] = {
static PyType_Spec Decomptype_spec = { static PyType_Spec Decomptype_spec = {
.name = "zlib.Decompress", .name = "zlib.Decompress",
.basicsize = sizeof(compobject), .basicsize = sizeof(compobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, .flags = (
Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_DISALLOW_INSTANTIATION
| Py_TPFLAGS_HAVE_GC
),
.slots = Decomptype_slots, .slots = Decomptype_slots,
}; };
static PyType_Slot ZlibDecompressor_type_slots[] = { static PyType_Slot ZlibDecompressor_type_slots[] = {
{Py_tp_dealloc, ZlibDecompressor_dealloc}, {Py_tp_dealloc, ZlibDecompressor_dealloc},
{Py_tp_traverse, ZlibDecompressor_traverse},
{Py_tp_members, ZlibDecompressor_members}, {Py_tp_members, ZlibDecompressor_members},
{Py_tp_new, zlib__ZlibDecompressor}, {Py_tp_new, zlib__ZlibDecompressor},
{Py_tp_doc, (char *)zlib__ZlibDecompressor__doc__}, {Py_tp_doc, (char *)zlib__ZlibDecompressor__doc__},
@ -2056,7 +2090,11 @@ static PyType_Spec ZlibDecompressor_type_spec = {
// ZlibDecompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // ZlibDecompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag
// which prevents to create a subclass. // which prevents to create a subclass.
// So calling PyType_GetModuleState() in this file is always safe. // So calling PyType_GetModuleState() in this file is always safe.
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), .flags = (
Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_IMMUTABLETYPE
| Py_TPFLAGS_HAVE_GC
),
.slots = ZlibDecompressor_type_slots, .slots = ZlibDecompressor_type_slots,
}; };