https://github.com/python/cpython/commit/b739bd1d4251368be9a2269290a0019eff9ee866
commit: b739bd1d4251368be9a2269290a0019eff9ee866
branch: 3.13
author: Inada Naoki <[email protected]>
committer: hugovk <[email protected]>
date: 2026-01-13T10:12:38Z
summary:
[3.13] gh-143189: fix insertdict() for non-Unicode key (GH-143285) (#143772)
files:
A Misc/NEWS.d/next/Core and
Builtins/2025-12-30-06-48-48.gh-issue-143189.in_sv2.rst
M Lib/test/test_dict.py
M Objects/dictobject.c
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index c7b6f64b53b42f..52ef0c14ea3a64 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -1655,6 +1655,7 @@ def make_pairs():
self.assertGreaterEqual(eq_count, 1)
def test_clear_at_lookup(self):
+ # gh-140551 dict crash if clear is called at lookup stage
class X:
def __hash__(self):
return 1
@@ -1675,6 +1676,8 @@ def __eq__(self, other):
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()
@@ -1682,6 +1685,22 @@ class MyClass: pass
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):
diff --git a/Misc/NEWS.d/next/Core and
Builtins/2025-12-30-06-48-48.gh-issue-143189.in_sv2.rst b/Misc/NEWS.d/next/Core
and Builtins/2025-12-30-06-48-48.gh-issue-143189.in_sv2.rst
new file mode 100644
index 00000000000000..706b9ded20c4f1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and
Builtins/2025-12-30-06-48-48.gh-issue-143189.in_sv2.rst
@@ -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.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index c987af31c45dd1..3e0537c18177a7 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1832,7 +1832,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);
@@ -1856,11 +1856,14 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
}
- 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;
}
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]