Skip to content

Commit a6b07b5

Browse files
authoredApr 19, 2023
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
 

Diff for: ‎Modules/cjkcodecs/cjkcodecs.h

+35-9
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)

Diff for: ‎Modules/cjkcodecs/multibytecodec.c

+15-4
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;

Diff for: ‎Modules/cjkcodecs/multibytecodec.h

+8-1
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)