[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)

787787

PyDictKeyEntry *ep;

788788

assert(key != dummy);

789789790+

Py_INCREF(key);

791+

Py_INCREF(value);

790792

if (mp->ma_values != NULL && !PyUnicode_CheckExact(key)) {

791793

if (insertion_resize(mp) < 0)

792-

return -1;

794+

goto Fail;

793795

}

794796795797

ep = 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+799801

assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict);

800-

Py_INCREF(value);

801802

MAINTAIN_TRACKING(mp, key, value);

802803

old_value = *value_addr;

803804

if (old_value != NULL) {

804805

assert(ep->me_key != NULL && ep->me_key != dummy);

805806

*value_addr = value;

806807

Py_DECREF(old_value); /* which **CAN** re-enter (see issue #22653) */

808+

Py_DECREF(key);

807809

}

808810

else {

809811

if (ep->me_key == NULL) {

810-

Py_INCREF(key);

811812

if (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;

818816

ep = find_empty_slot(mp, key, hash, &value_addr);

819817

}

818+

mp->ma_used++;

819+

*value_addr = value;

820820

mp->ma_keys->dk_usable--;

821821

assert(mp->ma_keys->dk_usable >= 0);

822822

ep->me_key = key;

823823

ep->me_hash = hash;

824+

assert(ep->me_key != NULL && ep->me_key != dummy);

824825

}

825826

else {

827+

mp->ma_used++;

828+

*value_addr = value;

826829

if (ep->me_key == dummy) {

827-

Py_INCREF(key);

828830

ep->me_key = key;

829831

ep->me_hash = hash;

830832

Py_DECREF(dummy);

831833

} else {

832834

assert(_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

}

839839

return 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. */

20582063

key = PySequence_Fast_GET_ITEM(fast, 0);

20592064

value = PySequence_Fast_GET_ITEM(fast, 1);

2065+

Py_INCREF(key);

2066+

Py_INCREF(value);

20602067

if (override || PyDict_GetItem(d, key) == NULL) {

20612068

int 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);

20652077

Py_DECREF(fast);

20662078

Py_DECREF(item);

20672079

}

@@ -2320,14 +2332,15 @@ dict_equal(PyDictObject *a, PyDictObject *b)

23202332

bval = NULL;

23212333

else

23222334

bval = *vaddr;

2323-

Py_DECREF(key);

23242335

if (bval == NULL) {

2336+

Py_DECREF(key);

23252337

Py_DECREF(aval);

23262338

if (PyErr_Occurred())

23272339

return -1;

23282340

return 0;

23292341

}

23302342

cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);

2343+

Py_DECREF(key);

23312344

Py_DECREF(aval);

23322345

if (cmp <= 0) /* error or not equal */

23332346

return cmp;

@@ -3152,7 +3165,7 @@ PyTypeObject PyDictIterValue_Type = {

3152316531533166

static PyObject *dictiter_iternextitem(dictiterobject *di)

31543167

{

3155-

PyObject *key, *value, *result = di->di_result;

3168+

PyObject *key, *value, *result;

31563169

Py_ssize_t i, mask, offset;

31573170

PyDictObject *d = di->di_dict;

31583171

PyObject **value_ptr;

@@ -3188,22 +3201,27 @@ static PyObject *dictiter_iternextitem(dictiterobject *di)

31883201

if (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 */

31923215

Py_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 {

31963219

result = PyTuple_New(2);

31973220

if (result == NULL)

31983221

return 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 */

32073225

return result;

3208322632093227

fail:

@@ -3696,6 +3714,7 @@ dictitems_iter(_PyDictViewObject *dv)

36963714

static int

36973715

dictitems_contains(_PyDictViewObject *dv, PyObject *obj)

36983716

{

3717+

int result;

36993718

PyObject *key, *value, *found;

37003719

if (dv->dv_dict == NULL)

37013720

return 0;

@@ -3709,7 +3728,10 @@ dictitems_contains(_PyDictViewObject *dv, PyObject *obj)

37093728

return -1;

37103729

return 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

}

3714373637153737

static PySequenceMethods dictitems_as_sequence = {