Skip to content

Commit 9baf9c0

Browse files
committed
gh-142557: fix UAF in bytearray.__mod__ via re-entrant argument's __repr__
1 parent 57d5699 commit 9baf9c0

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

Lib/test/test_bytes.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,19 @@ def test_bytearray_api(self):
13821382
except OSError:
13831383
pass
13841384

1385+
def test_mod_use_after_free(self):
1386+
# Prevent UAF in bytearray % (a1, a2) with re-entrant a[12].__repr__.
1387+
# Regression test for https://github.com/python/cpython/issues/142557.
1388+
fmt = bytearray(b"%a %a")
1389+
1390+
class S:
1391+
def __repr__(self):
1392+
fmt.clear()
1393+
return "E"
1394+
1395+
args = (S(), S())
1396+
self.assertRaises(BufferError, fmt.__mod__, args)
1397+
13851398
def test_reverse(self):
13861399
b = bytearray(b'hello')
13871400
self.assertEqual(b.reverse(), None)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a use-after-free crash in :meth:`bytearray.__mod__` when the
2+
:meth:`~object.__repr__` method of one of the arguments to format mutates
3+
the :class:`bytearray`. Patch by Bénédikt Tran.

Objects/bytearrayobject.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2837,7 +2837,15 @@ bytearray_mod_lock_held(PyObject *v, PyObject *w)
28372837
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(v);
28382838
if (!PyByteArray_Check(v))
28392839
Py_RETURN_NOTIMPLEMENTED;
2840-
return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
2840+
2841+
PyByteArrayObject *self = _PyByteArray_CAST(v);
2842+
/* Increase exports to prevent bytearray storage from changing during op. */
2843+
self->ob_exports++;
2844+
PyObject *res = _PyBytes_FormatEx(
2845+
PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1
2846+
);
2847+
self->ob_exports--;
2848+
return res;
28412849
}
28422850

28432851
static PyObject *

0 commit comments

Comments
 (0)