@@ -1724,6 +1724,14 @@ static inline int
17241724insert_combined_dict (PyInterpreterState * interp , PyDictObject * mp ,
17251725 Py_hash_t hash , PyObject * key , PyObject * value )
17261726{
1727+ // gh-140551: If dict was cleared in _Py_dict_lookup,
1728+ // we have to resize one more time to force general key kind.
1729+ if (DK_IS_UNICODE (mp -> ma_keys ) && !PyUnicode_CheckExact (key )) {
1730+ if (insertion_resize (interp , mp , 0 ) < 0 )
1731+ return -1 ;
1732+ assert (mp -> ma_keys -> dk_kind == DICT_KEYS_GENERAL );
1733+ }
1734+
17271735 if (mp -> ma_keys -> dk_usable <= 0 ) {
17281736 /* Need to resize. */
17291737 if (insertion_resize (interp , mp , 1 ) < 0 ) {
@@ -1825,40 +1833,34 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
18251833 PyObject * key , Py_hash_t hash , PyObject * value )
18261834{
18271835 PyObject * old_value ;
1836+ Py_ssize_t ix ;
18281837
18291838 ASSERT_DICT_LOCKED (mp );
18301839
1831- if (DK_IS_UNICODE (mp -> ma_keys ) && !PyUnicode_CheckExact (key )) {
1832- if (insertion_resize (interp , mp , 0 ) < 0 )
1833- goto Fail ;
1834- assert (mp -> ma_keys -> dk_kind == DICT_KEYS_GENERAL );
1835- }
1840+ MAINTAIN_TRACKING (mp , key , value );
18361841
1837- if (_PyDict_HasSplitTable (mp )) {
1838- Py_ssize_t ix = insert_split_key (mp -> ma_keys , key , hash );
1842+ if (_PyDict_HasSplitTable (mp ) && PyUnicode_CheckExact ( key ) ) {
1843+ ix = insert_split_key (mp -> ma_keys , key , hash );
18391844 if (ix != DKIX_EMPTY ) {
18401845 insert_split_value (interp , mp , key , value , ix );
18411846 Py_DECREF (key );
18421847 Py_DECREF (value );
18431848 return 0 ;
18441849 }
1845-
1846- /* No space in shared keys. Resize and continue below. */
1847- if (insertion_resize (interp , mp , 1 ) < 0 ) {
1848- goto Fail ;
1849- }
1850+ // No space in shared keys. Go to insert_combined_dict() below.
18501851 }
1852+ else {
1853+ ix = _Py_dict_lookup (mp , key , hash , & old_value );
1854+ if (ix == DKIX_ERROR )
1855+ goto Fail ;
18511856
1852- Py_ssize_t ix = _Py_dict_lookup (mp , key , hash , & old_value );
1853- if (ix == DKIX_ERROR )
1854- goto Fail ;
1855-
1856- MAINTAIN_TRACKING (mp , key , value );
1857+ }
18571858
18581859 if (ix == DKIX_EMPTY ) {
1859- assert (!_PyDict_HasSplitTable (mp ));
1860- /* Insert into new slot. */
1861- assert (old_value == NULL );
1860+ // insert_combined_dict() will convert from non DICT_KEYS_GENERAL table
1861+ // into DICT_KEYS_GENERAL table if key is not Unicode.
1862+ // We don't convert it before _Py_dict_lookup because non-Unicode key
1863+ // may change generic table into Unicode table.
18621864 if (insert_combined_dict (interp , mp , hash , key , value ) < 0 ) {
18631865 goto Fail ;
18641866 }
@@ -4256,6 +4258,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
42564258 PyDictObject * mp = (PyDictObject * )d ;
42574259 PyObject * value ;
42584260 Py_hash_t hash ;
4261+ Py_ssize_t ix ;
42594262 PyInterpreterState * interp = _PyInterpreterState_GET ();
42604263
42614264 ASSERT_DICT_LOCKED (d );
@@ -4290,17 +4293,8 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
42904293 return 0 ;
42914294 }
42924295
4293- if (!PyUnicode_CheckExact (key ) && DK_IS_UNICODE (mp -> ma_keys )) {
4294- if (insertion_resize (interp , mp , 0 ) < 0 ) {
4295- if (result ) {
4296- * result = NULL ;
4297- }
4298- return -1 ;
4299- }
4300- }
4301-
4302- if (_PyDict_HasSplitTable (mp )) {
4303- Py_ssize_t ix = insert_split_key (mp -> ma_keys , key , hash );
4296+ if (_PyDict_HasSplitTable (mp ) && PyUnicode_CheckExact (key )) {
4297+ ix = insert_split_key (mp -> ma_keys , key , hash );
43044298 if (ix != DKIX_EMPTY ) {
43054299 PyObject * value = mp -> ma_values -> values [ix ];
43064300 int already_present = value != NULL ;
@@ -4313,27 +4307,22 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
43134307 }
43144308 return already_present ;
43154309 }
4316-
4317- /* No space in shared keys. Resize and continue below. */
4318- if (insertion_resize (interp , mp , 1 ) < 0 ) {
4319- goto error ;
4320- }
4310+ // No space in shared keys. Go to insert_combined_dict() below.
43214311 }
4322-
4323- assert (! _PyDict_HasSplitTable ( mp ) );
4324-
4325- Py_ssize_t ix = _Py_dict_lookup ( mp , key , hash , & value );
4326- if ( ix == DKIX_ERROR ) {
4327- if ( result ) {
4328- * result = NULL ;
4312+ else {
4313+ ix = _Py_dict_lookup ( mp , key , hash , & value );
4314+ if ( ix == DKIX_ERROR ) {
4315+ if ( result ) {
4316+ * result = NULL ;
4317+ }
4318+ return -1 ;
43294319 }
4330- return -1 ;
43314320 }
43324321
43334322 if (ix == DKIX_EMPTY ) {
4334- assert (!_PyDict_HasSplitTable (mp ));
43354323 value = default_value ;
43364324
4325+ // See comment to this function in insertdict.
43374326 if (insert_combined_dict (interp , mp , hash , Py_NewRef (key ), Py_NewRef (value )) < 0 ) {
43384327 Py_DECREF (key );
43394328 Py_DECREF (value );
@@ -4359,12 +4348,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
43594348 * result = incref_result ? Py_NewRef (value ) : value ;
43604349 }
43614350 return 1 ;
4362-
4363- error :
4364- if (result ) {
4365- * result = NULL ;
4366- }
4367- return -1 ;
43684351}
43694352
43704353int
0 commit comments