Skip to content

Commit

Permalink
[3.11] gh-112625: Protect bytearray from being freed by misbehaving i…
Browse files Browse the repository at this point in the history
…terator inside bytearray.join (GH-112626) (GH-112694)

(cherry picked from commit 0e732d0)

Co-authored-by: chilaxan <[email protected]>
  • Loading branch information
miss-islington and chilaxan authored Dec 4, 2023
1 parent 3eea835 commit 7e89dd9
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 1 deletion.
17 changes: 17 additions & 0 deletions Lib/test/test_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1987,6 +1987,23 @@ def test_bytearray_extend_error(self):
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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 4 additions & 1 deletion Objects/bytearrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2008,7 +2008,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]
Expand Down

0 comments on commit 7e89dd9

Please sign in to comment.