Skip to content

Commit 61ee048

Browse files
authored
gh-142557: fix UAF in bytearray.__mod__ when object is mutated while formatting %-style arguments (#143213)
1 parent 84fcdbd commit 61ee048

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

Lib/test/test_bytes.py

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

1385+
def test_mod_concurrent_mutation(self):
1386+
# Prevent crash in __mod__ when formatting mutates the bytearray.
1387+
# Regression test for https://github.com/python/cpython/issues/142557.
1388+
fmt = bytearray(b"%a end")
1389+
1390+
class S:
1391+
def __repr__(self):
1392+
fmt.clear()
1393+
return "E"
1394+
1395+
self.assertRaises(BufferError, fmt.__mod__, S())
1396+
13851397
def test_reverse(self):
13861398
b = bytearray(b'hello')
13871399
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 :ref:`bytearray.__mod__ <bytes-formatting>` when
2+
the :class:`!bytearray` is mutated while formatting the ``%``-style arguments.
3+
Patch by Bénédikt Tran.

Objects/bytearrayobject.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2843,7 +2843,15 @@ bytearray_mod_lock_held(PyObject *v, PyObject *w)
28432843
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(v);
28442844
if (!PyByteArray_Check(v))
28452845
Py_RETURN_NOTIMPLEMENTED;
2846-
return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
2846+
2847+
PyByteArrayObject *self = _PyByteArray_CAST(v);
2848+
/* Increase exports to prevent bytearray storage from changing during op. */
2849+
self->ob_exports++;
2850+
PyObject *res = _PyBytes_FormatEx(
2851+
PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1
2852+
);
2853+
self->ob_exports--;
2854+
return res;
28472855
}
28482856

28492857
static PyObject *

0 commit comments

Comments
 (0)