From: chilaxan Date: Mon, 4 Dec 2023 08:15:43 +0000 (-0500) Subject: gh-112625: Protect bytearray from being freed by misbehaving iterator inside bytearra... X-Git-Tag: v3.13.0a3~543 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0e732d0997cff08855d98c17af4dd5527f10e419;p=thirdparty%2FPython%2Fcpython.git gh-112625: Protect bytearray from being freed by misbehaving iterator inside bytearray.join (GH-112626) --- diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index b7966f8f0387..535856adaea4 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -2039,6 +2039,23 @@ class BuiltinTest(unittest.TestCase): bad_iter = map(int, "X") self.assertRaises(ValueError, array.extend, bad_iter) + def test_bytearray_join_with_misbehaving_iterator(self): + # Issue #112625 + array = bytearray(b',') + def iterator(): + array.clear() + yield b'A' + yield b'B' + self.assertRaises(BufferError, array.join, iterator()) + + def test_bytearray_join_with_custom_iterator(self): + # Issue #112625 + array = bytearray(b',') + def iterator(): + yield b'A' + yield b'B' + self.assertEqual(bytearray(b'A,B'), array.join(iterator())) + def test_construct_singletons(self): for const in None, Ellipsis, NotImplemented: tp = type(const) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-03-19-34-51.gh-issue-112625.QWTlwS.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-03-19-34-51.gh-issue-112625.QWTlwS.rst new file mode 100644 index 000000000000..4970e10f3f4d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-03-19-34-51.gh-issue-112625.QWTlwS.rst @@ -0,0 +1 @@ +Fixes a bug where a bytearray object could be cleared while iterating over an argument in the ``bytearray.join()`` method that could result in reading memory after it was freed. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 67073190cc88..659de7d3dd5a 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2007,7 +2007,10 @@ static PyObject * bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes) /*[clinic end generated code: output=a8516370bf68ae08 input=aba6b1f9b30fcb8e]*/ { - return stringlib_bytes_join((PyObject*)self, iterable_of_bytes); + self->ob_exports++; // this protects `self` from being cleared/resized if `iterable_of_bytes` is a custom iterator + PyObject* ret = stringlib_bytes_join((PyObject*)self, iterable_of_bytes); + self->ob_exports--; // unexport `self` + return ret; } /*[clinic input]