@@ -1723,6 +1723,14 @@ static inline int
17231723insert_combined_dict (PyInterpreterState * interp , PyDictObject * mp ,
17241724 Py_hash_t hash , PyObject * key , PyObject * value )
17251725{
1726+ // gh-140551: If dict was cleared in _Py_dict_lookup,
1727+ // we have to resize one more time to force general key kind.
1728+ if (DK_IS_UNICODE (mp -> ma_keys ) && !PyUnicode_CheckExact (key )) {
1729+ if (insertion_resize (interp , mp , 0 ) < 0 )
1730+ return -1 ;
1731+ assert (mp -> ma_keys -> dk_kind == DICT_KEYS_GENERAL );
1732+ }
1733+
17261734 if (mp -> ma_keys -> dk_usable <= 0 ) {
17271735 /* Need to resize. */
17281736 if (insertion_resize (interp , mp , 1 ) < 0 ) {
@@ -1819,38 +1827,31 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
18191827 PyObject * key , Py_hash_t hash , PyObject * value )
18201828{
18211829 PyObject * old_value ;
1830+ Py_ssize_t ix ;
18221831
18231832 ASSERT_DICT_LOCKED (mp );
18241833
1825- if (DK_IS_UNICODE (mp -> ma_keys ) && !PyUnicode_CheckExact (key )) {
1826- if (insertion_resize (interp , mp , 0 ) < 0 )
1827- goto Fail ;
1828- assert (mp -> ma_keys -> dk_kind == DICT_KEYS_GENERAL );
1829- }
1830-
1831- if (_PyDict_HasSplitTable (mp )) {
1832- Py_ssize_t ix = insert_split_key (mp -> ma_keys , key , hash );
1834+ if (_PyDict_HasSplitTable (mp ) && PyUnicode_CheckExact (key )) {
1835+ ix = insert_split_key (mp -> ma_keys , key , hash );
18331836 if (ix != DKIX_EMPTY ) {
18341837 insert_split_value (interp , mp , key , value , ix );
18351838 Py_DECREF (key );
18361839 Py_DECREF (value );
18371840 return 0 ;
18381841 }
1839-
1840- /* No space in shared keys. Resize and continue below. */
1841- if (insertion_resize (interp , mp , 1 ) < 0 ) {
1842+ // No space in shared keys. Go to insert_combined_dict() below.
1843+ }
1844+ else {
1845+ ix = _Py_dict_lookup (mp , key , hash , & old_value );
1846+ if (ix == DKIX_ERROR )
18421847 goto Fail ;
1843- }
18441848 }
18451849
1846- Py_ssize_t ix = _Py_dict_lookup (mp , key , hash , & old_value );
1847- if (ix == DKIX_ERROR )
1848- goto Fail ;
1849-
18501850 if (ix == DKIX_EMPTY ) {
1851- assert (!_PyDict_HasSplitTable (mp ));
1852- /* Insert into new slot. */
1853- assert (old_value == NULL );
1851+ // insert_combined_dict() will convert from non DICT_KEYS_GENERAL table
1852+ // into DICT_KEYS_GENERAL table if key is not Unicode.
1853+ // We don't convert it before _Py_dict_lookup because non-Unicode key
1854+ // may change generic table into Unicode table.
18541855 if (insert_combined_dict (interp , mp , hash , key , value ) < 0 ) {
18551856 goto Fail ;
18561857 }
@@ -4326,6 +4327,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
43264327 PyDictObject * mp = (PyDictObject * )d ;
43274328 PyObject * value ;
43284329 Py_hash_t hash ;
4330+ Py_ssize_t ix ;
43294331 PyInterpreterState * interp = _PyInterpreterState_GET ();
43304332
43314333 ASSERT_DICT_LOCKED (d );
@@ -4361,17 +4363,8 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
43614363 return 0 ;
43624364 }
43634365
4364- if (!PyUnicode_CheckExact (key ) && DK_IS_UNICODE (mp -> ma_keys )) {
4365- if (insertion_resize (interp , mp , 0 ) < 0 ) {
4366- if (result ) {
4367- * result = NULL ;
4368- }
4369- return -1 ;
4370- }
4371- }
4372-
4373- if (_PyDict_HasSplitTable (mp )) {
4374- Py_ssize_t ix = insert_split_key (mp -> ma_keys , key , hash );
4366+ if (_PyDict_HasSplitTable (mp ) && PyUnicode_CheckExact (key )) {
4367+ ix = insert_split_key (mp -> ma_keys , key , hash );
43754368 if (ix != DKIX_EMPTY ) {
43764369 PyObject * value = mp -> ma_values -> values [ix ];
43774370 int already_present = value != NULL ;
@@ -4384,27 +4377,22 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
43844377 }
43854378 return already_present ;
43864379 }
4387-
4388- /* No space in shared keys. Resize and continue below. */
4389- if (insertion_resize (interp , mp , 1 ) < 0 ) {
4390- goto error ;
4391- }
4380+ // No space in shared keys. Go to insert_combined_dict() below.
43924381 }
4393-
4394- assert (! _PyDict_HasSplitTable ( mp ) );
4395-
4396- Py_ssize_t ix = _Py_dict_lookup ( mp , key , hash , & value );
4397- if ( ix == DKIX_ERROR ) {
4398- if ( result ) {
4399- * result = NULL ;
4382+ else {
4383+ ix = _Py_dict_lookup ( mp , key , hash , & value );
4384+ if ( ix == DKIX_ERROR ) {
4385+ if ( result ) {
4386+ * result = NULL ;
4387+ }
4388+ return -1 ;
44004389 }
4401- return -1 ;
44024390 }
44034391
44044392 if (ix == DKIX_EMPTY ) {
4405- assert (!_PyDict_HasSplitTable (mp ));
44064393 value = default_value ;
44074394
4395+ // See comment to this function in insertdict.
44084396 if (insert_combined_dict (interp , mp , hash , Py_NewRef (key ), Py_NewRef (value )) < 0 ) {
44094397 Py_DECREF (key );
44104398 Py_DECREF (value );
@@ -4429,12 +4417,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
44294417 * result = incref_result ? Py_NewRef (value ) : value ;
44304418 }
44314419 return 1 ;
4432-
4433- error :
4434- if (result ) {
4435- * result = NULL ;
4436- }
4437- return -1 ;
44384420}
44394421
44404422int
0 commit comments