@@ -1775,6 +1775,14 @@ static inline int
17751775insert_combined_dict (PyInterpreterState * interp , PyDictObject * mp ,
17761776 Py_hash_t hash , PyObject * key , PyObject * value )
17771777{
1778+ // gh-140551: If dict was cleared in _Py_dict_lookup,
1779+ // we have to resize one more time to force general key kind.
1780+ if (DK_IS_UNICODE (mp -> ma_keys ) && !PyUnicode_CheckExact (key )) {
1781+ if (insertion_resize (mp , 0 ) < 0 )
1782+ return -1 ;
1783+ assert (mp -> ma_keys -> dk_kind == DICT_KEYS_GENERAL );
1784+ }
1785+
17781786 if (mp -> ma_keys -> dk_usable <= 0 ) {
17791787 /* Need to resize. */
17801788 if (insertion_resize (mp , 1 ) < 0 ) {
@@ -1871,38 +1879,31 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
18711879 PyObject * key , Py_hash_t hash , PyObject * value )
18721880{
18731881 PyObject * old_value ;
1882+ Py_ssize_t ix ;
18741883
18751884 ASSERT_DICT_LOCKED (mp );
18761885
1877- if (DK_IS_UNICODE (mp -> ma_keys ) && !PyUnicode_CheckExact (key )) {
1878- if (insertion_resize (mp , 0 ) < 0 )
1879- goto Fail ;
1880- assert (mp -> ma_keys -> dk_kind == DICT_KEYS_GENERAL );
1881- }
1882-
1883- if (_PyDict_HasSplitTable (mp )) {
1884- Py_ssize_t ix = insert_split_key (mp -> ma_keys , key , hash );
1886+ if (_PyDict_HasSplitTable (mp ) && PyUnicode_CheckExact (key )) {
1887+ ix = insert_split_key (mp -> ma_keys , key , hash );
18851888 if (ix != DKIX_EMPTY ) {
18861889 insert_split_value (interp , mp , key , value , ix );
18871890 Py_DECREF (key );
18881891 Py_DECREF (value );
18891892 return 0 ;
18901893 }
1891-
1892- /* No space in shared keys. Resize and continue below. */
1893- if (insertion_resize (mp , 1 ) < 0 ) {
1894+ // No space in shared keys. Go to insert_combined_dict() below.
1895+ }
1896+ else {
1897+ ix = _Py_dict_lookup (mp , key , hash , & old_value );
1898+ if (ix == DKIX_ERROR )
18941899 goto Fail ;
1895- }
18961900 }
18971901
1898- Py_ssize_t ix = _Py_dict_lookup (mp , key , hash , & old_value );
1899- if (ix == DKIX_ERROR )
1900- goto Fail ;
1901-
19021902 if (ix == DKIX_EMPTY ) {
1903- assert (!_PyDict_HasSplitTable (mp ));
1904- /* Insert into new slot. */
1905- assert (old_value == NULL );
1903+ // insert_combined_dict() will convert from non DICT_KEYS_GENERAL table
1904+ // into DICT_KEYS_GENERAL table if key is not Unicode.
1905+ // We don't convert it before _Py_dict_lookup because non-Unicode key
1906+ // may change generic table into Unicode table.
19061907 if (insert_combined_dict (interp , mp , hash , key , value ) < 0 ) {
19071908 goto Fail ;
19081909 }
@@ -4374,6 +4375,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
43744375 PyDictObject * mp = (PyDictObject * )d ;
43754376 PyObject * value ;
43764377 Py_hash_t hash ;
4378+ Py_ssize_t ix ;
43774379 PyInterpreterState * interp = _PyInterpreterState_GET ();
43784380
43794381 ASSERT_DICT_LOCKED (d );
@@ -4409,17 +4411,8 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
44094411 return 0 ;
44104412 }
44114413
4412- if (!PyUnicode_CheckExact (key ) && DK_IS_UNICODE (mp -> ma_keys )) {
4413- if (insertion_resize (mp , 0 ) < 0 ) {
4414- if (result ) {
4415- * result = NULL ;
4416- }
4417- return -1 ;
4418- }
4419- }
4420-
4421- if (_PyDict_HasSplitTable (mp )) {
4422- Py_ssize_t ix = insert_split_key (mp -> ma_keys , key , hash );
4414+ if (_PyDict_HasSplitTable (mp ) && PyUnicode_CheckExact (key )) {
4415+ ix = insert_split_key (mp -> ma_keys , key , hash );
44234416 if (ix != DKIX_EMPTY ) {
44244417 PyObject * value = mp -> ma_values -> values [ix ];
44254418 int already_present = value != NULL ;
@@ -4432,27 +4425,22 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
44324425 }
44334426 return already_present ;
44344427 }
4435-
4436- /* No space in shared keys. Resize and continue below. */
4437- if (insertion_resize (mp , 1 ) < 0 ) {
4438- goto error ;
4439- }
4428+ // No space in shared keys. Go to insert_combined_dict() below.
44404429 }
4441-
4442- assert (! _PyDict_HasSplitTable ( mp ) );
4443-
4444- Py_ssize_t ix = _Py_dict_lookup ( mp , key , hash , & value );
4445- if ( ix == DKIX_ERROR ) {
4446- if ( result ) {
4447- * result = NULL ;
4430+ else {
4431+ ix = _Py_dict_lookup ( mp , key , hash , & value );
4432+ if ( ix == DKIX_ERROR ) {
4433+ if ( result ) {
4434+ * result = NULL ;
4435+ }
4436+ return -1 ;
44484437 }
4449- return -1 ;
44504438 }
44514439
44524440 if (ix == DKIX_EMPTY ) {
4453- assert (!_PyDict_HasSplitTable (mp ));
44544441 value = default_value ;
44554442
4443+ // See comment to this function in insertdict.
44564444 if (insert_combined_dict (interp , mp , hash , Py_NewRef (key ), Py_NewRef (value )) < 0 ) {
44574445 Py_DECREF (key );
44584446 Py_DECREF (value );
@@ -4477,12 +4465,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
44774465 * result = incref_result ? Py_NewRef (value ) : value ;
44784466 }
44794467 return 1 ;
4480-
4481- error :
4482- if (result ) {
4483- * result = NULL ;
4484- }
4485- return -1 ;
44864468}
44874469
44884470int
0 commit comments