Skip to content

Commit e62d5c6

Browse files
committed
gh-139122: Fix crash when pickling a C UUID without is_safe
UUID.__getstate__() passed a NULL is_safe to PyDict_SetItem() for every UUID created without is_safe. Omit the key, as the Python version does for SafeUUID.unknown.
1 parent 7dd8b47 commit e62d5c6

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

‎Lib/test/test_uuid.py‎

100755100644
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,26 @@ def check(actual, expected):
495495
with self.subTest(protocol=proto):
496496
check(pickle.loads(pickle.dumps(u, proto)), u)
497497

498+
def test_pickle_roundtrip_default_is_safe(self):
499+
def check(actual, expected):
500+
self.assertEqual(actual, expected)
501+
self.assertEqual(actual.is_safe, expected.is_safe)
502+
503+
with support.swap_item(sys.modules, 'uuid', self.uuid):
504+
uuids = [
505+
self.uuid.UUID('d82579ce6642a0de7ddf490a7aec7aa5'),
506+
self.uuid.UUID(int=1),
507+
self.uuid.uuid4(),
508+
self.uuid.uuid7(),
509+
]
510+
for u in uuids:
511+
with self.subTest(u=u):
512+
self.assertEqual(u.is_safe, self.uuid.SafeUUID.unknown)
513+
check(copy.copy(u), u)
514+
check(copy.deepcopy(u), u)
515+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
516+
check(pickle.loads(pickle.dumps(u, proto)), u)
517+
498518
def test_setstate_mapping(self):
499519
# State restoration accepts mappings and decodes serialized safety values.
500520
safety_states = [({}, self.uuid.SafeUUID.unknown)]

‎Modules/_uuidmodule.c‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,10 @@ _uuid_UUID___getstate___impl(uuidobject *self)
16211621
}
16221622
Py_DECREF(int_value);
16231623

1624-
if (PyDict_SetItem(dict, &_Py_ID(is_safe), self->is_safe) < 0) {
1624+
// NULL means SafeUUID.unknown, which __setstate__() restores by default.
1625+
if (self->is_safe != NULL &&
1626+
PyDict_SetItem(dict, &_Py_ID(is_safe), self->is_safe) < 0)
1627+
{
16251628
Py_DECREF(dict);
16261629
return NULL;
16271630
}

0 commit comments

Comments
 (0)