gh-142557: fix UAF in bytearray.__mod__ when object is mutated while formatting %-style arguments (#143213)

This commit is contained in:
Bénédikt Tran 2025-12-27 14:57:13 +00:00 committed by GitHub
parent 84fcdbd86e
commit 61ee04834b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 1 deletions

View file

@ -1382,6 +1382,18 @@ def test_bytearray_api(self):
except OSError:
pass
def test_mod_concurrent_mutation(self):
# Prevent crash in __mod__ when formatting mutates the bytearray.
# Regression test for https://github.com/python/cpython/issues/142557.
fmt = bytearray(b"%a end")
class S:
def __repr__(self):
fmt.clear()
return "E"
self.assertRaises(BufferError, fmt.__mod__, S())
def test_reverse(self):
b = bytearray(b'hello')
self.assertEqual(b.reverse(), None)

View file

@ -0,0 +1,3 @@
Fix a use-after-free crash in :ref:`bytearray.__mod__ <bytes-formatting>` when
the :class:`!bytearray` is mutated while formatting the ``%``-style arguments.
Patch by Bénédikt Tran.

View file

@ -2843,7 +2843,15 @@ bytearray_mod_lock_held(PyObject *v, PyObject *w)
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(v);
if (!PyByteArray_Check(v))
Py_RETURN_NOTIMPLEMENTED;
return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
PyByteArrayObject *self = _PyByteArray_CAST(v);
/* Increase exports to prevent bytearray storage from changing during op. */
self->ob_exports++;
PyObject *res = _PyBytes_FormatEx(
PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1
);
self->ob_exports--;
return res;
}
static PyObject *