From 77d9d68812411191f3ca9437382734381dbde0df Mon Sep 17 00:00:00 2001 From: Crowthebird <78076854+thatbirdguythatuknownot@users.noreply.github.com> Date: Mon, 14 Mar 2022 09:23:59 +0800 Subject: [PATCH] bpo-39829: Fix `__len__()` is called twice in list() constructor (GH-31816) (cherry picked from commit 2153daf0a02a598ed5df93f2f224c1ab2a2cca0d) Co-authored-by: Crowthebird <78076854+thatbirdguythatuknownot@users.noreply.github.com> --- Misc/ACKS | 1 + .../2022-03-11-09-39-01.bpo-39829.mlW3Su.rst | 1 + Objects/listobject.c | 29 ++++++++----------- 3 files changed, 14 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-03-11-09-39-01.bpo-39829.mlW3Su.rst diff --git a/Misc/ACKS b/Misc/ACKS index 889bf8aeaea1ac..b83f99956de0b1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1332,6 +1332,7 @@ William Park Claude Paroz Heikki Partanen Harri Pasanen +Jeremiah Gabriel Pascual Gaƫl Pasgrimaud Feanil Patel Ashish Nitin Patil diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-11-09-39-01.bpo-39829.mlW3Su.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-11-09-39-01.bpo-39829.mlW3Su.rst new file mode 100644 index 00000000000000..1f3d945188a32a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-11-09-39-01.bpo-39829.mlW3Su.rst @@ -0,0 +1 @@ +Removed the ``__len__()`` call when initializing a list and moved initializing to ``list_extend``. Patch by Jeremiah Pascual. diff --git a/Objects/listobject.c b/Objects/listobject.c index d3bc5766df7a0b..7f37b7386051d0 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -863,7 +863,6 @@ list_extend(PyListObject *self, PyObject *iterable) PyObject *it; /* iter(v) */ Py_ssize_t m; /* size of self */ Py_ssize_t n; /* guess for size of iterable */ - Py_ssize_t mn; /* m + n */ Py_ssize_t i; PyObject *(*iternext)(PyObject *); @@ -887,7 +886,13 @@ list_extend(PyListObject *self, PyObject *iterable) /* It should not be possible to allocate a list large enough to cause an overflow on any relevant platform */ assert(m < PY_SSIZE_T_MAX - n); - if (list_resize(self, m + n) < 0) { + if (self->ob_item == NULL) { + if (list_preallocate_exact(self, n) < 0) { + return NULL; + } + Py_SET_SIZE(self, n); + } + else if (list_resize(self, m + n) < 0) { Py_DECREF(iterable); return NULL; } @@ -926,10 +931,13 @@ list_extend(PyListObject *self, PyObject *iterable) * eventually run out of memory during the loop. */ } + else if (self->ob_item == NULL) { + if (n && list_preallocate_exact(self, n) < 0) + goto error; + } else { - mn = m + n; /* Make room. */ - if (list_resize(self, mn) < 0) + if (list_resize(self, m + n) < 0) goto error; /* Make the list sane again. */ Py_SET_SIZE(self, m); @@ -2717,19 +2725,6 @@ list___init___impl(PyListObject *self, PyObject *iterable) (void)_list_clear(self); } if (iterable != NULL) { - if (_PyObject_HasLen(iterable)) { - Py_ssize_t iter_len = PyObject_Size(iterable); - if (iter_len == -1) { - if (!PyErr_ExceptionMatches(PyExc_TypeError)) { - return -1; - } - PyErr_Clear(); - } - if (iter_len > 0 && self->ob_item == NULL - && list_preallocate_exact(self, iter_len)) { - return -1; - } - } PyObject *rv = list_extend(self, iterable); if (rv == NULL) return -1;