Skip to content

Commit e0e255e

Browse files
[3.13] gh-143003: Fix possible shared buffer overflow in bytearray.extend() (GH-143086) (GH-143448)
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 44bdb83 commit e0e255e

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
@@ -1941,6 +1941,23 @@ def make_case():
19411941
with self.assertRaises(BufferError):
19421942
ba.rsplit(evil)
19431943

1944+
def test_extend_empty_buffer_overflow(self):
1945+
# gh-143003
1946+
class EvilIter:
1947+
def __iter__(self):
1948+
return self
1949+
def __next__(self):
1950+
return next(source)
1951+
def __length_hint__(self):
1952+
return 0
1953+
1954+
# Use ASCII digits so float() takes the fast path that expects a NUL terminator.
1955+
source = iter(b'42')
1956+
ba = bytearray()
1957+
ba.extend(EvilIter())
1958+
1959+
self.assertRaises(ValueError, float, bytearray())
1960+
19441961
def test_hex_use_after_free(self):
19451962
# Prevent UAF in bytearray.hex(sep) with re-entrant sep.__len__.
19461963
# 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
@@ -1871,7 +1871,6 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
18711871
Py_DECREF(bytearray_obj);
18721872
return NULL;
18731873
}
1874-
buf[len++] = value;
18751874
Py_DECREF(item);
18761875

18771876
if (len >= buf_size) {
@@ -1881,7 +1880,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
18811880
Py_DECREF(bytearray_obj);
18821881
return PyErr_NoMemory();
18831882
}
1884-
addition = len >> 1;
1883+
addition = len ? len >> 1 : 1;
18851884
if (addition > PY_SSIZE_T_MAX - len - 1)
18861885
buf_size = PY_SSIZE_T_MAX;
18871886
else
@@ -1895,6 +1894,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
18951894
have invalidated it. */
18961895
buf = PyByteArray_AS_STRING(bytearray_obj);
18971896
}
1897+
buf[len++] = value;
18981898
}
18991899
Py_DECREF(it);
19001900

0 commit comments

Comments
 (0)