From 2153daf0a02a598ed5df93f2f224c1ab2a2cca0d 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) --- Misc/ACKS | 2 +- .../2022-03-11-09-39-01.bpo-39829.mlW3Su.rst | 1 + Objects/listobject.c | 29 ++++++++----------- 3 files changed, 14 insertions(+), 18 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 84fcb322d4086a..00194f40f074af 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1336,6 +1336,7 @@ William Park Claude Paroz Heikki Partanen Harri Pasanen +Jeremiah Gabriel Pascual Gaƫl Pasgrimaud Feanil Patel Ashish Nitin Patil @@ -1864,7 +1865,6 @@ Kurt Vile Norman Vine Pauli Virtanen Frank Visser -Jeremiah Vivian (Pascual) Johannes Vogel Michael Vogt Radu Voicilas 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 783ae88a17f3be..d50633d2b31321 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -865,7 +865,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 *); @@ -889,7 +888,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; } @@ -928,10 +933,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); @@ -2814,19 +2822,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;