diff -urNp Python-2.7.5/Python/bltinmodule.c Python-2.7.5.new/Python/bltinmodule.c --- Python-2.7.5/Python/bltinmodule.c 2013-05-12 06:32:53.000000000 +0300 +++ Python-2.7.5.new/Python/bltinmodule.c 2013-06-26 07:23:28.000000000 +0300 @@ -2401,32 +2393,43 @@ builtin_sum(PyObject *self, PyObject *ar } #endif - for(;;) { - item = PyIter_Next(iter); - if (item == NULL) { - /* error, or end-of-sequence */ - if (PyErr_Occurred()) { - Py_DECREF(result); - result = NULL; - } - break; - } - /* It's tempting to use PyNumber_InPlaceAdd instead of - PyNumber_Add here, to avoid quadratic running time - when doing 'sum(list_of_lists, [])'. However, this - would produce a change in behaviour: a snippet like - - empty = [] - sum([[x] for x in range(10)], empty) - - would change the value of empty. */ - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) - break; - } + /* Add first item separately to make sure we won't change + start object in cases like: + + empty = [] + sum([[x] for x in range(10)], empty) + + */ + item = PyIter_Next(iter); + if (item != NULL) { + temp = PyNumber_Add(result, item); + Py_DECREF(result); + Py_DECREF(item); + result = temp; + item = PyIter_Next(iter); + } + + /* Now add all the other items */ + while (item != NULL && result != NULL) { + temp = PyNumber_InPlaceAdd(result, item); + Py_DECREF(result); + Py_DECREF(item); + result = temp; + item = PyIter_Next(iter); + } + + /* Cleanup if PyNumber_(InPlace)Add returned NULL */ + if (item != NULL) { + Py_DECREF(item); + } + else { + /* error, or end-of-sequence */ + if (result != NULL && PyErr_Occurred()) { + Py_DECREF(result); + result = NULL; + } + } + Py_DECREF(iter); return result; }