[3.14] gh-143189: fix insertdict() for non-Unicode key (GH-143285) (#143771)

This commit is contained in:
Inada Naoki 2026-01-13 18:58:53 +09:00 committed by GitHub
parent af89f7cacd
commit 5d26a0410e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 2 deletions

View File

@ -1602,6 +1602,7 @@ class DictTest(unittest.TestCase):
d.get(key2)
def test_clear_at_lookup(self):
# gh-140551 dict crash if clear is called at lookup stage
class X:
def __hash__(self):
return 1
@ -1622,6 +1623,8 @@ class DictTest(unittest.TestCase):
self.assertEqual(len(d), 1)
def test_split_table_update_with_str_subclass(self):
# gh-142218: inserting into a split table dictionary with a non str
# key that matches an existing key.
class MyStr(str): pass
class MyClass: pass
obj = MyClass()
@ -1629,6 +1632,22 @@ class DictTest(unittest.TestCase):
obj.__dict__[MyStr('attr')] = 2
self.assertEqual(obj.attr, 2)
def test_split_table_insert_with_str_subclass(self):
# gh-143189: inserting into split table dictionary with a non str
# key that matches an existing key in the shared table but not in
# the dict yet.
class MyStr(str): pass
class MyClass: pass
obj = MyClass()
obj.attr1 = 1
obj2 = MyClass()
d = obj2.__dict__
d[MyStr("attr1")] = 2
self.assertIsInstance(list(d)[0], MyStr)
class CAPITest(unittest.TestCase):

View File

@ -0,0 +1,3 @@
Fix crash when inserting a non-:class:`str` key into a split table
dictionary when the key matches an existing key in the split table
but has no corresponding value in the dict.

View File

@ -1826,7 +1826,7 @@ static int
insertdict(PyInterpreterState *interp, PyDictObject *mp,
PyObject *key, Py_hash_t hash, PyObject *value)
{
PyObject *old_value;
PyObject *old_value = NULL;
Py_ssize_t ix;
ASSERT_DICT_LOCKED(mp);
@ -1847,11 +1847,14 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
goto Fail;
}
if (ix == DKIX_EMPTY) {
if (old_value == NULL) {
// insert_combined_dict() will convert from non DICT_KEYS_GENERAL table
// into DICT_KEYS_GENERAL table if key is not Unicode.
// We don't convert it before _Py_dict_lookup because non-Unicode key
// may change generic table into Unicode table.
//
// NOTE: ix may not be DKIX_EMPTY because split table may have key
// without value.
if (insert_combined_dict(interp, mp, hash, key, value) < 0) {
goto Fail;
}