Skip to content

Commit 5a63d35

Browse files
authored
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.
1 parent 4ecf6ca commit 5a63d35

3 files changed

Lines changed: 19 additions & 0 deletions

File tree

‎Lib/test/test_bytes.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,6 +2499,16 @@ def test_reinit_with_view(self):
24992499
self.assertRaises(BufferError, a.__init__, "x", "ascii")
25002500
self.assertEqual(a, b"")
25012501

2502+
def test_reinit_error(self):
2503+
# A failed __init__() must not leave uninitialized bytes in the
2504+
# object: it must be empty afterwards.
2505+
for source in ([256] * 100, (-1,) * 100, [0] * 50 + [1000],
2506+
(1, 2, 1 << 100)):
2507+
with self.subTest(source=source):
2508+
a = bytearray(b"abc")
2509+
self.assertRaises(ValueError, a.__init__, source)
2510+
self.assertEqual(a, b"")
2511+
25022512

25032513
class AssortedBytesTest(unittest.TestCase):
25042514
#
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :meth:`!bytearray.__init__` leaving uninitialized memory in the object
2+
when it fails on a :class:`list` or :class:`tuple` containing an integer not
3+
in ``range(256)``. The object is now empty after the failed call.

‎Objects/bytearrayobject.c‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,11 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject *arg,
10841084
if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
10851085
if (PyBuffer_ToContiguous(PyByteArray_AS_STRING(self),
10861086
&view, size, 'C') < 0)
1087+
{
1088+
/* Don't expose the uninitialized bytes: reset to empty */
1089+
(void)PyByteArray_Resize((PyObject *)self, 0);
10871090
goto fail;
1091+
}
10881092
PyBuffer_Release(&view);
10891093
return 0;
10901094
fail:
@@ -1112,6 +1116,8 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject *arg,
11121116
}
11131117
int rc = _getbytevalue(items[i], &value);
11141118
if (!rc) {
1119+
/* Don't expose the uninitialized bytes: reset to empty */
1120+
(void)PyByteArray_Resize((PyObject *)self, 0);
11151121
return -1;
11161122
}
11171123
s[i] = value;

0 commit comments

Comments
 (0)