]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39829: Fix `__len__()` is called twice in list() constructor (GH-31816)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 18 May 2022 04:16:58 +0000 (21:16 -0700)
committerGitHub <noreply@github.com>
Wed, 18 May 2022 04:16:58 +0000 (13:16 +0900)
(cherry picked from commit 2153daf0a02a598ed5df93f2f224c1ab2a2cca0d)

This patch fixes gh-87740 too.

Co-authored-by: Crowthebird <78076854+thatbirdguythatuknownot@users.noreply.github.com>
Misc/ACKS
Misc/NEWS.d/next/Core and Builtins/2022-03-11-09-39-01.bpo-39829.mlW3Su.rst [new file with mode: 0644]
Objects/listobject.c

index 889bf8aeaea1accb088051f519357f0ed9f7c04a..b83f99956de0b1e6a018ee595e4b372f30e0d027 100644 (file)
--- 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 (file)
index 0000000..1f3d945
--- /dev/null
@@ -0,0 +1 @@
+Removed the ``__len__()`` call when initializing a list and moved initializing to ``list_extend``. Patch by Jeremiah Pascual.
index d3bc5766df7a0bea82f08e1b69ac0f9b8a255731..7f37b7386051d0ebe25cb0145c5665fb3bfdcb2d 100644 (file)
@@ -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;