Skip to content

Commit 7e89dd9

Browse files
[3.11] gh-112625: Protect bytearray from being freed by misbehaving iterator inside bytearray.join (GH-112626) (GH-112694)
(cherry picked from commit 0e732d0) Co-authored-by: chilaxan <[email protected]>
1 parent 3eea835 commit 7e89dd9

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

Lib/test/test_builtin.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,23 @@ def test_bytearray_extend_error(self):
19871987
bad_iter = map(int, "X")
19881988
self.assertRaises(ValueError, array.extend, bad_iter)
19891989

1990+
def test_bytearray_join_with_misbehaving_iterator(self):
1991+
# Issue #112625
1992+
array = bytearray(b',')
1993+
def iterator():
1994+
array.clear()
1995+
yield b'A'
1996+
yield b'B'
1997+
self.assertRaises(BufferError, array.join, iterator())
1998+
1999+
def test_bytearray_join_with_custom_iterator(self):
2000+
# Issue #112625
2001+
array = bytearray(b',')
2002+
def iterator():
2003+
yield b'A'
2004+
yield b'B'
2005+
self.assertEqual(bytearray(b'A,B'), array.join(iterator()))
2006+
19902007
def test_construct_singletons(self):
19912008
for const in None, Ellipsis, NotImplemented:
19922009
tp = type(const)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

Objects/bytearrayobject.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2008,7 +2008,10 @@ static PyObject *
20082008
bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes)
20092009
/*[clinic end generated code: output=a8516370bf68ae08 input=aba6b1f9b30fcb8e]*/
20102010
{
2011-
return stringlib_bytes_join((PyObject*)self, iterable_of_bytes);
2011+
self->ob_exports++; // this protects `self` from being cleared/resized if `iterable_of_bytes` is a custom iterator
2012+
PyObject* ret = stringlib_bytes_join((PyObject*)self, iterable_of_bytes);
2013+
self->ob_exports--; // unexport `self`
2014+
return ret;
20122015
}
20132016

20142017
/*[clinic input]

0 commit comments

Comments
 (0)