Skip to content

Commit beee2f0

Browse files
gh-143003: Fix possible shared buffer overflow in bytearray.extend()
When __length_hint__() returns 0 for non-empty iterator, the data can be written past the shared 0-terminated buffer, corrupting it.
1 parent 665d280 commit beee2f0

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

Lib/test/test_bytes.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,24 @@ def make_case():
20922092
with self.assertRaises(BufferError):
20932093
ba.rsplit(evil)
20942094

2095+
def test_extend_empty_buffer_overflow(self):
2096+
# gh-143003
2097+
class EvilIter:
2098+
def __iter__(self):
2099+
return self
2100+
def __next__(self):
2101+
return next(source)
2102+
def __length_hint__(self):
2103+
return 0
2104+
2105+
# Use ASCII digits so float() takes the fast path that expects a NUL terminator.
2106+
source = iter(b'42')
2107+
ba = bytearray()
2108+
ba.extend(EvilIter())
2109+
2110+
self.assertRaises(ValueError, float, bytearray())
2111+
2112+
20952113
class AssortedBytesTest(unittest.TestCase):
20962114
#
20972115
# Test various combinations of bytes and bytearray
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an overflow of the shared empty buffer in :meth:`bytearray.extend` when
2+
``__length_hint__()`` returns 0 for non-empty iterator.

Objects/bytearrayobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,7 +2223,6 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
22232223
Py_DECREF(bytearray_obj);
22242224
return NULL;
22252225
}
2226-
buf[len++] = value;
22272226
Py_DECREF(item);
22282227

22292228
if (len >= buf_size) {
@@ -2233,7 +2232,7 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
22332232
Py_DECREF(bytearray_obj);
22342233
return PyErr_NoMemory();
22352234
}
2236-
addition = len >> 1;
2235+
addition = len ? len >> 1 : 1;
22372236
if (addition > PyByteArray_SIZE_MAX - len)
22382237
buf_size = PyByteArray_SIZE_MAX;
22392238
else
@@ -2247,6 +2246,7 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
22472246
have invalidated it. */
22482247
buf = PyByteArray_AS_STRING(bytearray_obj);
22492248
}
2249+
buf[len++] = value;
22502250
}
22512251
Py_DECREF(it);
22522252

0 commit comments

Comments
 (0)