[2.7] bpo-27945: Fixed various segfaults with dict. (GH-1657) (#1681)
Based on patches by Duane Griffin and Tim Mitchell.
(cherry picked from commit 753bca3934a7618a4fa96e107ad1c5c18633a683)
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 870923d..9506067 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1595,11 +1595,18 @@
/* Update/merge with this (key, value) pair. */
key = PySequence_Fast_GET_ITEM(fast, 0);
value = PySequence_Fast_GET_ITEM(fast, 1);
+ Py_INCREF(key);
+ Py_INCREF(value);
if (override || PyDict_GetItem(d, key) == NULL) {
int status = PyDict_SetItem(d, key, value);
- if (status < 0)
+ if (status < 0) {
+ Py_DECREF(key);
+ Py_DECREF(value);
goto Fail;
+ }
}
+ Py_DECREF(key);
+ Py_DECREF(value);
Py_DECREF(fast);
Py_DECREF(item);
}
@@ -1938,12 +1945,13 @@
/* ditto for key */
Py_INCREF(key);
bval = PyDict_GetItem((PyObject *)b, key);
- Py_DECREF(key);
if (bval == NULL) {
+ Py_DECREF(key);
Py_DECREF(aval);
return 0;
}
cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
+ Py_DECREF(key);
Py_DECREF(aval);
if (cmp <= 0) /* error or not equal */
return cmp;
@@ -2743,7 +2751,7 @@
static PyObject *dictiter_iternextitem(dictiterobject *di)
{
- PyObject *key, *value, *result = di->di_result;
+ PyObject *key, *value, *result;
register Py_ssize_t i, mask;
register PyDictEntry *ep;
PyDictObject *d = di->di_dict;
@@ -2770,22 +2778,27 @@
if (i > mask)
goto fail;
- if (result->ob_refcnt == 1) {
- Py_INCREF(result);
- Py_DECREF(PyTuple_GET_ITEM(result, 0));
- Py_DECREF(PyTuple_GET_ITEM(result, 1));
- } else {
- result = PyTuple_New(2);
- if (result == NULL)
- return NULL;
- }
di->len--;
key = ep[i].me_key;
value = ep[i].me_value;
Py_INCREF(key);
Py_INCREF(value);
- PyTuple_SET_ITEM(result, 0, key);
- PyTuple_SET_ITEM(result, 1, value);
+ result = di->di_result;
+ if (Py_REFCNT(result) == 1) {
+ PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
+ PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
+ PyTuple_SET_ITEM(result, 0, key); /* steals reference */
+ PyTuple_SET_ITEM(result, 1, value); /* steals reference */
+ Py_INCREF(result);
+ Py_DECREF(oldkey);
+ Py_DECREF(oldvalue);
+ } else {
+ result = PyTuple_New(2);
+ if (result == NULL)
+ return NULL;
+ PyTuple_SET_ITEM(result, 0, key); /* steals reference */
+ PyTuple_SET_ITEM(result, 1, value); /* steals reference */
+ }
return result;
fail:
@@ -3186,6 +3199,7 @@
static int
dictitems_contains(dictviewobject *dv, PyObject *obj)
{
+ int result;
PyObject *key, *value, *found;
if (dv->dv_dict == NULL)
return 0;
@@ -3199,7 +3213,10 @@
return -1;
return 0;
}
- return PyObject_RichCompareBool(value, found, Py_EQ);
+ Py_INCREF(found);
+ result = PyObject_RichCompareBool(value, found, Py_EQ);
+ Py_DECREF(found);
+ return result;
}
static PySequenceMethods dictitems_as_sequence = {