Skip to content

Commit 1f24c14

Browse files
committed
Get module state assuming there could be subclasses of UUID
This fixes a segfault; regr test added
1 parent 712eae3 commit 1f24c14

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

Lib/test/test_uuid.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,17 @@ def test_exact_same_algo_uuid7(self):
16631663
finally:
16641664
self._reset_hooks(uuid)
16651665

1666+
def test_subclassing(self):
1667+
import uuid
1668+
1669+
class U(uuid._c_UUID):
1670+
pass
1671+
1672+
u = U(int=1)
1673+
u_str = str(u)
1674+
del u
1675+
self.assertEqual(u_str, '00000000-0000-0000-0000-000000000001')
1676+
16661677

16671678
if __name__ == '__main__':
16681679
unittest.main()

Modules/_uuidmodule.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ uuid_getpid(void) {
211211
#endif
212212
}
213213

214+
static struct PyModuleDef uuidmodule;
215+
214216
static inline uuid_state *
215217
get_uuid_state(PyObject *mod)
216218
{
@@ -222,7 +224,9 @@ get_uuid_state(PyObject *mod)
222224
static inline uuid_state *
223225
get_uuid_state_by_cls(PyTypeObject *cls)
224226
{
225-
uuid_state *state = (uuid_state *)PyType_GetModuleState(cls);
227+
PyObject *module = PyType_GetModuleByDef(cls, &uuidmodule);
228+
assert(module != NULL);
229+
uuid_state *state = get_uuid_state(module);
226230
assert(state != NULL);
227231
return state;
228232
}
@@ -1019,18 +1023,25 @@ Uuid_dealloc(PyObject *obj)
10191023
}
10201024
Py_CLEAR(uuid->is_safe);
10211025

1022-
int added_to_freelist = 0;
1026+
int skip_dealloc = 0;
1027+
if (type != state->UuidType) {
1028+
// We only apply the freelist optimization to the known C type,
1029+
// not any subclasses of it.
1030+
goto dealloc;
1031+
}
1032+
10231033
Py_BEGIN_CRITICAL_SECTION(type);
10241034
if (state->freelist_size < MAX_FREE_LIST_SIZE) {
10251035
uuidobject *head = state->freelist;
10261036
state->freelist = uuid;
10271037
uuid->weakreflist = (PyObject *)head;
10281038
state->freelist_size++;
1029-
added_to_freelist = 1;
1039+
skip_dealloc = 1;
10301040
}
10311041
Py_END_CRITICAL_SECTION();
10321042

1033-
if (!added_to_freelist) {
1043+
dealloc:
1044+
if (!skip_dealloc) {
10341045
type->tp_free(uuid);
10351046
// UUID is a heap allocated type so we have to decref the type ref
10361047
Py_DECREF(type);

0 commit comments

Comments
 (0)