Skip to content

Commit 9f91278

Browse files
[3.14] gh-143003: Fix possible shared buffer overflow in bytearray.extend() (GH-143086) (GH-143447)
When __length_hint__() returns 0 for non-empty iterator, the data can be written past the shared 0-terminated buffer, corrupting it. (cherry picked from commit 5225635) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent c889ff6 commit 9f91278

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

Lib/test/test_bytes.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,23 @@ def make_case():
20132013
with self.assertRaises(BufferError):
20142014
ba.rsplit(evil)
20152015

2016+
def test_extend_empty_buffer_overflow(self):
2017+
# gh-143003
2018+
class EvilIter:
2019+
def __iter__(self):
2020+
return self
2021+
def __next__(self):
2022+
return next(source)
2023+
def __length_hint__(self):
2024+
return 0
2025+
2026+
# Use ASCII digits so float() takes the fast path that expects a NUL terminator.
2027+
source = iter(b'42')
2028+
ba = bytearray()
2029+
ba.extend(EvilIter())
2030+
2031+
self.assertRaises(ValueError, float, bytearray())
2032+
20162033
def test_hex_use_after_free(self):
20172034
# Prevent UAF in bytearray.hex(sep) with re-entrant sep.__len__.
20182035
# Regression test for https://github.com/python/cpython/issues/143195.
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
@@ -2182,7 +2182,6 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
21822182
Py_DECREF(bytearray_obj);
21832183
return NULL;
21842184
}
2185-
buf[len++] = value;
21862185
Py_DECREF(item);
21872186

21882187
if (len >= buf_size) {
@@ -2192,7 +2191,7 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
21922191
Py_DECREF(bytearray_obj);
21932192
return PyErr_NoMemory();
21942193
}
2195-
addition = len >> 1;
2194+
addition = len ? len >> 1 : 1;
21962195
if (addition > PY_SSIZE_T_MAX - len - 1)
21972196
buf_size = PY_SSIZE_T_MAX;
21982197
else
@@ -2206,6 +2205,7 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
22062205
have invalidated it. */
22072206
buf = PyByteArray_AS_STRING(bytearray_obj);
22082207
}
2208+
buf[len++] = value;
22092209
}
22102210
Py_DECREF(it);
22112211

0 commit comments

Comments
 (0)