]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-143003: Fix possible shared buffer overflow in bytearray.extend() (GH-143086)
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 28 Dec 2025 12:30:36 +0000 (14:30 +0200)
committerGitHub <noreply@github.com>
Sun, 28 Dec 2025 12:30:36 +0000 (12:30 +0000)
When __length_hint__() returns 0 for non-empty iterator, the data can be
written past the shared 0-terminated buffer, corrupting it.

Lib/test/test_bytes.py
Misc/NEWS.d/next/Core_and_Builtins/2025-12-23-00-13-02.gh-issue-143003.92g5qW.rst [new file with mode: 0644]
Objects/bytearrayobject.c

index e0baeece34c7b3393776baa53f742425360d0002..c42c0d4f5e9bc2fc508457743842bb2636a6dec9 100644 (file)
@@ -2104,6 +2104,23 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
         with self.assertRaises(BufferError):
             ba.rsplit(evil)
 
+    def test_extend_empty_buffer_overflow(self):
+        # gh-143003
+        class EvilIter:
+            def __iter__(self):
+                return self
+            def __next__(self):
+                return next(source)
+            def __length_hint__(self):
+                return 0
+
+        # Use ASCII digits so float() takes the fast path that expects a NUL terminator.
+        source = iter(b'42')
+        ba = bytearray()
+        ba.extend(EvilIter())
+
+        self.assertRaises(ValueError, float, bytearray())
+
     def test_hex_use_after_free(self):
         # Prevent UAF in bytearray.hex(sep) with re-entrant sep.__len__.
         # Regression test for https://github.com/python/cpython/issues/143195.
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-23-00-13-02.gh-issue-143003.92g5qW.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-23-00-13-02.gh-issue-143003.92g5qW.rst
new file mode 100644 (file)
index 0000000..30df3c5
--- /dev/null
@@ -0,0 +1,2 @@
+Fix an overflow of the shared empty buffer in :meth:`bytearray.extend` when
+``__length_hint__()`` returns 0 for non-empty iterator.
index 5262ac20c073009d49fee00209a02c8d08605fd7..7f09769e12f05fc3b07a1b17ab85cc33d34947bc 100644 (file)
@@ -2223,7 +2223,6 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
             Py_DECREF(bytearray_obj);
             return NULL;
         }
-        buf[len++] = value;
         Py_DECREF(item);
 
         if (len >= buf_size) {
@@ -2233,7 +2232,7 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
                 Py_DECREF(bytearray_obj);
                 return PyErr_NoMemory();
             }
-            addition = len >> 1;
+            addition = len ? len >> 1 : 1;
             if (addition > PyByteArray_SIZE_MAX - len)
                 buf_size = PyByteArray_SIZE_MAX;
             else
@@ -2247,6 +2246,7 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
                have invalidated it. */
             buf = PyByteArray_AS_STRING(bytearray_obj);
         }
+        buf[len++] = value;
     }
     Py_DECREF(it);