https://github.com/python/cpython/commit/e0e255e244dd16fbb4dd38bb40f2055d518dce15
commit: e0e255e244dd16fbb4dd38bb40f2055d518dce15
branch: 3.13
author: Stan Ulbrych <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-01-06T13:49:31+02:00
summary:

[3.13] gh-143003: Fix possible shared buffer overflow in bytearray.extend() 
(GH-143086) (GH-143448)

When __length_hint__() returns 0 for non-empty iterator, the data can be
written past the shared 0-terminated buffer, corrupting it.
(cherry picked from commit 522563549a49d28e763635c58274a23a6055f041)

Co-authored-by: Serhiy Storchaka <[email protected]>

files:
A Misc/NEWS.d/next/Core and 
Builtins/2025-12-23-00-13-02.gh-issue-143003.92g5qW.rst
M Lib/test/test_bytes.py
M Objects/bytearrayobject.c

diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 91687a90a2c073..56bdfe373191d4 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -1941,6 +1941,23 @@ def make_case():
         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
index 00000000000000..30df3c53abd29f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2025-12-23-00-13-02.gh-issue-143003.92g5qW.rst 
@@ -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.
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 5e29dd8e69d10e..feea0aef276118 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -1871,7 +1871,6 @@ bytearray_extend(PyByteArrayObject *self, PyObject 
*iterable_of_ints)
             Py_DECREF(bytearray_obj);
             return NULL;
         }
-        buf[len++] = value;
         Py_DECREF(item);
 
         if (len >= buf_size) {
@@ -1881,7 +1880,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject 
*iterable_of_ints)
                 Py_DECREF(bytearray_obj);
                 return PyErr_NoMemory();
             }
-            addition = len >> 1;
+            addition = len ? len >> 1 : 1;
             if (addition > PY_SSIZE_T_MAX - len - 1)
                 buf_size = PY_SSIZE_T_MAX;
             else
@@ -1895,6 +1894,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject 
*iterable_of_ints)
                have invalidated it. */
             buf = PyByteArray_AS_STRING(bytearray_obj);
         }
+        buf[len++] = value;
     }
     Py_DECREF(it);
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to