https://github.com/python/cpython/commit/19fda670d6061584de873ba8f9c27aad742c0fbb
commit: 19fda670d6061584de873ba8f9c27aad742c0fbb
branch: 3.13
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2025-12-27T17:20:49Z
summary:
[3.13] gh-142557: fix UAF in `bytearray.__mod__` when object is mutated while
formatting `%`-style arguments (GH-143213) (#143229)
(cherry picked from commit 61ee04834b096be00678c6819b4957f3f4413a5e)
files:
A Misc/NEWS.d/next/Core and
Builtins/2025-12-27-12-25-06.gh-issue-142557.KWOc8b.rst
M Lib/test/test_bytes.py
M Objects/bytearrayobject.c
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 3e948f3577977f..91687a90a2c073 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -1349,6 +1349,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)
diff --git a/Misc/NEWS.d/next/Core and
Builtins/2025-12-27-12-25-06.gh-issue-142557.KWOc8b.rst b/Misc/NEWS.d/next/Core
and Builtins/2025-12-27-12-25-06.gh-issue-142557.KWOc8b.rst
new file mode 100644
index 00000000000000..b7f7a585906c34
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and
Builtins/2025-12-27-12-25-06.gh-issue-142557.KWOc8b.rst
@@ -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.
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index f4e4e2885d80bc..5e29dd8e69d10e 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -2401,7 +2401,15 @@ bytearray_mod(PyObject *v, PyObject *w)
{
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 PyNumberMethods bytearray_as_number = {
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]