[3.5] bpo-27945: Fixed various segfaults with dict. (GH-1657) (#1678) · python/cpython@2f7f533
@@ -787,56 +787,61 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
787787PyDictKeyEntry *ep;
788788assert(key != dummy);
789789790+Py_INCREF(key);
791+Py_INCREF(value);
790792if (mp->ma_values != NULL && !PyUnicode_CheckExact(key)) {
791793if (insertion_resize(mp) < 0)
792-return -1;
794+goto Fail;
793795 }
794796795797ep = mp->ma_keys->dk_lookup(mp, key, hash, &value_addr);
796-if (ep == NULL) {
797-return -1;
798- }
798+if (ep == NULL)
799+goto Fail;
800+799801assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict);
800-Py_INCREF(value);
801802MAINTAIN_TRACKING(mp, key, value);
802803old_value = *value_addr;
803804if (old_value != NULL) {
804805assert(ep->me_key != NULL && ep->me_key != dummy);
805806*value_addr = value;
806807Py_DECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
808+Py_DECREF(key);
807809 }
808810else {
809811if (ep->me_key == NULL) {
810-Py_INCREF(key);
811812if (mp->ma_keys->dk_usable <= 0) {
812813/* Need to resize. */
813-if (insertion_resize(mp) < 0) {
814-Py_DECREF(key);
815-Py_DECREF(value);
816-return -1;
817- }
814+if (insertion_resize(mp) < 0)
815+ goto Fail;
818816ep = find_empty_slot(mp, key, hash, &value_addr);
819817 }
818+mp->ma_used++;
819+*value_addr = value;
820820mp->ma_keys->dk_usable--;
821821assert(mp->ma_keys->dk_usable >= 0);
822822ep->me_key = key;
823823ep->me_hash = hash;
824+assert(ep->me_key != NULL && ep->me_key != dummy);
824825 }
825826else {
827+mp->ma_used++;
828+*value_addr = value;
826829if (ep->me_key == dummy) {
827-Py_INCREF(key);
828830ep->me_key = key;
829831ep->me_hash = hash;
830832Py_DECREF(dummy);
831833 } else {
832834assert(_PyDict_HasSplitTable(mp));
835+Py_DECREF(key);
833836 }
834837 }
835-mp->ma_used++;
836-*value_addr = value;
837-assert(ep->me_key != NULL && ep->me_key != dummy);
838838 }
839839return 0;
840+841+Fail:
842+Py_DECREF(value);
843+Py_DECREF(key);
844+return -1;
840845}
841846842847/*
@@ -2057,11 +2062,18 @@ PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
20572062/* Update/merge with this (key, value) pair. */
20582063key = PySequence_Fast_GET_ITEM(fast, 0);
20592064value = PySequence_Fast_GET_ITEM(fast, 1);
2065+Py_INCREF(key);
2066+Py_INCREF(value);
20602067if (override || PyDict_GetItem(d, key) == NULL) {
20612068int status = PyDict_SetItem(d, key, value);
2062-if (status < 0)
2069+if (status < 0) {
2070+Py_DECREF(key);
2071+Py_DECREF(value);
20632072 goto Fail;
2073+ }
20642074 }
2075+Py_DECREF(key);
2076+Py_DECREF(value);
20652077Py_DECREF(fast);
20662078Py_DECREF(item);
20672079 }
@@ -2320,14 +2332,15 @@ dict_equal(PyDictObject *a, PyDictObject *b)
23202332bval = NULL;
23212333else
23222334bval = *vaddr;
2323-Py_DECREF(key);
23242335if (bval == NULL) {
2336+Py_DECREF(key);
23252337Py_DECREF(aval);
23262338if (PyErr_Occurred())
23272339return -1;
23282340return 0;
23292341 }
23302342cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
2343+Py_DECREF(key);
23312344Py_DECREF(aval);
23322345if (cmp <= 0) /* error or not equal */
23332346return cmp;
@@ -3152,7 +3165,7 @@ PyTypeObject PyDictIterValue_Type = {
3152316531533166static PyObject *dictiter_iternextitem(dictiterobject *di)
31543167{
3155-PyObject *key, *value, *result = di->di_result;
3168+PyObject *key, *value, *result;
31563169Py_ssize_t i, mask, offset;
31573170PyDictObject *d = di->di_dict;
31583171PyObject **value_ptr;
@@ -3188,22 +3201,27 @@ static PyObject *dictiter_iternextitem(dictiterobject *di)
31883201if (i > mask)
31893202 goto fail;
319032033191-if (result->ob_refcnt == 1) {
3204+di->len--;
3205+key = d->ma_keys->dk_entries[i].me_key;
3206+value = *value_ptr;
3207+Py_INCREF(key);
3208+Py_INCREF(value);
3209+result = di->di_result;
3210+if (Py_REFCNT(result) == 1) {
3211+PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
3212+PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
3213+PyTuple_SET_ITEM(result, 0, key); /* steals reference */
3214+PyTuple_SET_ITEM(result, 1, value); /* steals reference */
31923215Py_INCREF(result);
3193-Py_DECREF(PyTuple_GET_ITEM(result, 0));
3194-Py_DECREF(PyTuple_GET_ITEM(result, 1));
3216+Py_DECREF(oldkey);
3217+Py_DECREF(oldvalue);
31953218 } else {
31963219result = PyTuple_New(2);
31973220if (result == NULL)
31983221return NULL;
3222+PyTuple_SET_ITEM(result, 0, key); /* steals reference */
3223+PyTuple_SET_ITEM(result, 1, value); /* steals reference */
31993224 }
3200-di->len--;
3201-key = d->ma_keys->dk_entries[i].me_key;
3202-value = *value_ptr;
3203-Py_INCREF(key);
3204-Py_INCREF(value);
3205-PyTuple_SET_ITEM(result, 0, key); /* steals reference */
3206-PyTuple_SET_ITEM(result, 1, value); /* steals reference */
32073225return result;
3208322632093227fail:
@@ -3696,6 +3714,7 @@ dictitems_iter(_PyDictViewObject *dv)
36963714static int
36973715dictitems_contains(_PyDictViewObject *dv, PyObject *obj)
36983716{
3717+int result;
36993718PyObject *key, *value, *found;
37003719if (dv->dv_dict == NULL)
37013720return 0;
@@ -3709,7 +3728,10 @@ dictitems_contains(_PyDictViewObject *dv, PyObject *obj)
37093728return -1;
37103729return 0;
37113730 }
3712-return PyObject_RichCompareBool(value, found, Py_EQ);
3731+Py_INCREF(found);
3732+result = PyObject_RichCompareBool(value, found, Py_EQ);
3733+Py_DECREF(found);
3734+return result;
37133735}
3714373637153737static PySequenceMethods dictitems_as_sequence = {