diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 05faad4532b867c..9c36fbed9eb19af 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -2499,6 +2499,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 000000000000000..5377e59a60ea48d --- /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 9c0127ee4751b60..87f8da4af53ae56 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1087,7 +1087,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: @@ -1115,6 +1119,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;