Skip to content

Commit a6b07b5

Browse files
gh-103583: Add ref. dependency between multibytecodec modules (#103589)
1 parent bd2ed06 commit a6b07b5

File tree

3 files changed

+58
-14
lines changed

3 files changed

+58
-14
lines changed

Modules/cjkcodecs/cjkcodecs.h

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -284,18 +284,45 @@ getmultibytecodec(void)
284284
return _PyImport_GetModuleAttrString("_multibytecodec", "__create_codec");
285285
}
286286

287+
static void
288+
destroy_codec_capsule(PyObject *capsule)
289+
{
290+
void *ptr = PyCapsule_GetPointer(capsule, CODEC_CAPSULE);
291+
codec_capsule *data = (codec_capsule *)ptr;
292+
Py_DECREF(data->cjk_module);
293+
PyMem_Free(ptr);
294+
}
295+
296+
static codec_capsule *
297+
capsulate_codec(PyObject *mod, const MultibyteCodec *codec)
298+
{
299+
codec_capsule *data = PyMem_Malloc(sizeof(codec_capsule));
300+
if (data == NULL) {
301+
PyErr_NoMemory();
302+
return NULL;
303+
}
304+
data->codec = codec;
305+
data->cjk_module = Py_NewRef(mod);
306+
return data;
307+
}
308+
287309
static PyObject *
288-
_getcodec(const MultibyteCodec *codec)
310+
_getcodec(PyObject *self, const MultibyteCodec *codec)
289311
{
290312
PyObject *cofunc = getmultibytecodec();
291313
if (cofunc == NULL) {
292314
return NULL;
293315
}
294316

295-
PyObject *codecobj = PyCapsule_New((void *)codec,
296-
PyMultibyteCodec_CAPSULE_NAME,
297-
NULL);
317+
codec_capsule *data = capsulate_codec(self, codec);
318+
if (data == NULL) {
319+
Py_DECREF(cofunc);
320+
return NULL;
321+
}
322+
PyObject *codecobj = PyCapsule_New(data, CODEC_CAPSULE,
323+
destroy_codec_capsule);
298324
if (codecobj == NULL) {
325+
PyMem_Free(data);
299326
Py_DECREF(cofunc);
300327
return NULL;
301328
}
@@ -323,7 +350,7 @@ getcodec(PyObject *self, PyObject *encoding)
323350
for (int i = 0; i < st->num_codecs; i++) {
324351
const MultibyteCodec *codec = &st->codec_list[i];
325352
if (strcmp(codec->encoding, enc) == 0) {
326-
return _getcodec(codec);
353+
return _getcodec(self, codec);
327354
}
328355
}
329356

@@ -352,8 +379,7 @@ register_maps(PyObject *module)
352379
char mhname[256] = "__map_";
353380
strcpy(mhname + sizeof("__map_") - 1, h->charset);
354381

355-
PyObject *capsule = PyCapsule_New((void *)h,
356-
PyMultibyteCodec_CAPSULE_NAME, NULL);
382+
PyObject *capsule = PyCapsule_New((void *)h, MAP_CAPSULE, NULL);
357383
if (capsule == NULL) {
358384
return -1;
359385
}
@@ -417,14 +443,14 @@ importmap(const char *modname, const char *symbol,
417443
o = PyObject_GetAttrString(mod, symbol);
418444
if (o == NULL)
419445
goto errorexit;
420-
else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) {
446+
else if (!PyCapsule_IsValid(o, MAP_CAPSULE)) {
421447
PyErr_SetString(PyExc_ValueError,
422448
"map data must be a Capsule.");
423449
goto errorexit;
424450
}
425451
else {
426452
struct dbcs_map *map;
427-
map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME);
453+
map = PyCapsule_GetPointer(o, MAP_CAPSULE);
428454
if (encmap != NULL)
429455
*encmap = map->encmap;
430456
if (decmap != NULL)

Modules/cjkcodecs/multibytecodec.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -720,9 +720,17 @@ static struct PyMethodDef multibytecodec_methods[] = {
720720
};
721721

722722
static int
723-
multibytecodec_traverse(PyObject *self, visitproc visit, void *arg)
723+
multibytecodec_clear(MultibyteCodecObject *self)
724+
{
725+
Py_CLEAR(self->cjk_module);
726+
return 0;
727+
}
728+
729+
static int
730+
multibytecodec_traverse(MultibyteCodecObject *self, visitproc visit, void *arg)
724731
{
725732
Py_VISIT(Py_TYPE(self));
733+
Py_VISIT(self->cjk_module);
726734
return 0;
727735
}
728736

@@ -731,6 +739,7 @@ multibytecodec_dealloc(MultibyteCodecObject *self)
731739
{
732740
PyObject_GC_UnTrack(self);
733741
PyTypeObject *tp = Py_TYPE(self);
742+
(void)multibytecodec_clear(self);
734743
tp->tp_free(self);
735744
Py_DECREF(tp);
736745
}
@@ -740,6 +749,7 @@ static PyType_Slot multibytecodec_slots[] = {
740749
{Py_tp_getattro, PyObject_GenericGetAttr},
741750
{Py_tp_methods, multibytecodec_methods},
742751
{Py_tp_traverse, multibytecodec_traverse},
752+
{Py_tp_clear, multibytecodec_clear},
743753
{0, NULL},
744754
};
745755

@@ -1953,14 +1963,14 @@ _multibytecodec___create_codec(PyObject *module, PyObject *arg)
19531963
/*[clinic end generated code: output=cfa3dce8260e809d input=6840b2a6b183fcfa]*/
19541964
{
19551965
MultibyteCodecObject *self;
1956-
const MultibyteCodec *codec;
19571966

1958-
if (!PyCapsule_IsValid(arg, PyMultibyteCodec_CAPSULE_NAME)) {
1967+
if (!PyCapsule_IsValid(arg, CODEC_CAPSULE)) {
19591968
PyErr_SetString(PyExc_ValueError, "argument type invalid");
19601969
return NULL;
19611970
}
19621971

1963-
codec = PyCapsule_GetPointer(arg, PyMultibyteCodec_CAPSULE_NAME);
1972+
codec_capsule *data = PyCapsule_GetPointer(arg, CODEC_CAPSULE);
1973+
const MultibyteCodec *codec = data->codec;
19641974
if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0)
19651975
return NULL;
19661976

@@ -1969,6 +1979,7 @@ _multibytecodec___create_codec(PyObject *module, PyObject *arg)
19691979
if (self == NULL)
19701980
return NULL;
19711981
self->codec = codec;
1982+
self->cjk_module = Py_NewRef(data->cjk_module);
19721983

19731984
PyObject_GC_Track(self);
19741985
return (PyObject *)self;

Modules/cjkcodecs/multibytecodec.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ typedef struct {
6363
typedef struct {
6464
PyObject_HEAD
6565
const MultibyteCodec *codec;
66+
PyObject *cjk_module;
6667
} MultibyteCodecObject;
6768

6869
#define MultibyteCodec_Check(state, op) Py_IS_TYPE((op), state->multibytecodec_type)
@@ -130,7 +131,13 @@ typedef struct {
130131
#define MBENC_FLUSH 0x0001 /* encode all characters encodable */
131132
#define MBENC_MAX MBENC_FLUSH
132133

133-
#define PyMultibyteCodec_CAPSULE_NAME "multibytecodec.__map_*"
134+
typedef struct {
135+
const MultibyteCodec *codec;
136+
PyObject *cjk_module;
137+
} codec_capsule;
138+
139+
#define MAP_CAPSULE "multibytecodec.map"
140+
#define CODEC_CAPSULE "multibytecodec.codec"
134141

135142

136143
#ifdef __cplusplus

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy