From 8110dbd470f3daa4de58dda66d360e3c26d3b94f Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 25 Sep 2017 02:15:53 -0700 Subject: [PATCH] bpo-26491 Defer DECREFs until enumobject is in a consistent state (#3747) --- Objects/enumobject.c | 48 +++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 3eb1736200c..154d901e86d 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -103,6 +103,8 @@ enum_next_long(enumobject *en, PyObject* next_item) PyObject *result = en->en_result; PyObject *next_index; PyObject *stepped_up; + PyObject *old_index; + PyObject *old_item; if (en->en_longindex == NULL) { en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX); @@ -118,15 +120,19 @@ enum_next_long(enumobject *en, PyObject* next_item) 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) { - Py_DECREF(next_index); - Py_DECREF(next_item); - return NULL; - } + old_index = PyTuple_GET_ITEM(result, 0); + old_item = PyTuple_GET_ITEM(result, 1); + PyTuple_SET_ITEM(result, 0, next_index); + PyTuple_SET_ITEM(result, 1, next_item); + Py_DECREF(old_index); + Py_DECREF(old_item); + return result; + } + result = PyTuple_New(2); + if (result == NULL) { + Py_DECREF(next_index); + Py_DECREF(next_item); + return NULL; } PyTuple_SET_ITEM(result, 0, next_index); PyTuple_SET_ITEM(result, 1, next_item); @@ -140,6 +146,8 @@ enum_next(enumobject *en) PyObject *next_item; PyObject *result = en->en_result; PyObject *it = en->en_sit; + PyObject *old_index; + PyObject *old_item; next_item = (*Py_TYPE(it)->tp_iternext)(it); if (next_item == NULL) @@ -157,15 +165,19 @@ enum_next(enumobject *en) 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) { - Py_DECREF(next_index); - Py_DECREF(next_item); - return NULL; - } + old_index = PyTuple_GET_ITEM(result, 0); + old_item = PyTuple_GET_ITEM(result, 1); + PyTuple_SET_ITEM(result, 0, next_index); + PyTuple_SET_ITEM(result, 1, next_item); + Py_DECREF(old_index); + Py_DECREF(old_item); + return result; + } + result = PyTuple_New(2); + if (result == NULL) { + Py_DECREF(next_index); + Py_DECREF(next_item); + return NULL; } PyTuple_SET_ITEM(result, 0, next_index); PyTuple_SET_ITEM(result, 1, next_item);