https://github.com/python/cpython/commit/fa795c294f414c06e05e7f9df77ef70338c7b56f
commit: fa795c294f414c06e05e7f9df77ef70338c7b56f
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: gpshead <[email protected]>
date: 2026-10-22T05:53:01Z
summary:

[3.15] gh-160179: Leave bytearray empty when __init__() fails midway 
(GH-160180) (#160202)

gh-160179: Leave bytearray empty when __init__() fails midway (GH-160180)

The list/tuple fast path and the buffer path resized the object before
filling it and did not undo the resize on error, leaving stale bytes.
(cherry picked from commit 5a63d3568197ac470561e95cbc744c1bc679f80d)

Co-authored-by: Gregory P. Smith <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-02.gh-issue-160179.dQ2e7m.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 4b4857295663dc..d402654c887a43 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -2404,6 +2404,16 @@ def test_reinit_with_view(self):
             self.assertRaises(BufferError, a.__init__, "x", "ascii")
         self.assertEqual(a, b"")
 
+    def test_reinit_error(self):
+        # A failed __init__() must not leave uninitialized bytes in the
+        # object: it must be empty afterwards.
+        for source in ([256] * 100, (-1,) * 100, [0] * 50 + [1000],
+                       (1, 2, 1 << 100)):
+            with self.subTest(source=source):
+                a = bytearray(b"abc")
+                self.assertRaises(ValueError, a.__init__, source)
+                self.assertEqual(a, b"")
+
 
 class AssortedBytesTest(unittest.TestCase):
     #
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-02.gh-issue-160179.dQ2e7m.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-02.gh-issue-160179.dQ2e7m.rst
new file mode 100644
index 00000000000000..5377e59a60ea48
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-02.gh-issue-160179.dQ2e7m.rst
@@ -0,0 +1,3 @@
+Fix :meth:`!bytearray.__init__` leaving uninitialized memory in the object
+when it fails on a :class:`list` or :class:`tuple` containing an integer not
+in ``range(256)``. The object is now empty after the failed call.
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 579d5cbadd0b39..0fa1ca0334245f 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -1086,7 +1086,11 @@ bytearray___init___impl(PyByteArrayObject *self, 
PyObject *arg,
         if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
         if (PyBuffer_ToContiguous(PyByteArray_AS_STRING(self),
             &view, size, 'C') < 0)
+        {
+            /* Don't expose the uninitialized bytes: reset to empty */
+            (void)PyByteArray_Resize((PyObject *)self, 0);
             goto fail;
+        }
         PyBuffer_Release(&view);
         return 0;
     fail:
@@ -1114,6 +1118,8 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject 
*arg,
             }
             int rc = _getbytevalue(items[i], &value);
             if (!rc) {
+                /* Don't expose the uninitialized bytes: reset to empty */
+                (void)PyByteArray_Resize((PyObject *)self, 0);
                 return -1;
             }
             s[i] = value;

_______________________________________________
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