https://github.com/python/cpython/commit/9976c2b6349a079ae39931d960b8c147e21c6c3f
commit: 9976c2b6349a079ae39931d960b8c147e21c6c3f
branch: main
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2025-12-27T13:32:52+01:00
summary:
gh-143195: fix UAF in `{bytearray,memoryview}.hex(sep)` via re-entrant
`sep.__len__` (#143209)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2025-12-27-10-14-26.gh-issue-143195.MNldfr.rst
M Lib/test/test_bytes.py
M Lib/test/test_memoryview.py
M Objects/bytearrayobject.c
M Objects/memoryobject.c
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 21be61e4fec720..44b16c7d91e996 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -2092,6 +2092,19 @@ def make_case():
with self.assertRaises(BufferError):
ba.rsplit(evil)
+ def test_hex_use_after_free(self):
+ # Prevent UAF in bytearray.hex(sep) with re-entrant sep.__len__.
+ # Regression test for https://github.com/python/cpython/issues/143195.
+ ba = bytearray(b'\xAA')
+
+ class S(bytes):
+ def __len__(self):
+ ba.clear()
+ return 1
+
+ self.assertRaises(BufferError, ba.hex, S(b':'))
+
+
class AssortedBytesTest(unittest.TestCase):
#
# Test various combinations of bytes and bytearray
diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py
index 1bd58eb6408833..51b107103f6836 100644
--- a/Lib/test/test_memoryview.py
+++ b/Lib/test/test_memoryview.py
@@ -442,6 +442,20 @@ def test_issue22668(self):
self.assertEqual(c.format, "H")
self.assertEqual(d.format, "H")
+ def test_hex_use_after_free(self):
+ # Prevent UAF in memoryview.hex(sep) with re-entrant sep.__len__.
+ # Regression test for https://github.com/python/cpython/issues/143195.
+ ba = bytearray(b'A' * 1024)
+ mv = memoryview(ba)
+
+ class S(bytes):
+ def __len__(self):
+ mv.release()
+ ba.clear()
+ return 1
+
+ self.assertRaises(BufferError, mv.hex, S(b':'))
+
# Variations on source objects for the buffer: bytes-like objects, then arrays
# with itemsize > 1.
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-27-10-14-26.gh-issue-143195.MNldfr.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-27-10-14-26.gh-issue-143195.MNldfr.rst
new file mode 100644
index 00000000000000..66dc5e22f0ab23
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-27-10-14-26.gh-issue-143195.MNldfr.rst
@@ -0,0 +1,3 @@
+Fix use-after-free crashes in :meth:`bytearray.hex` and :meth:`memoryview.hex`
+when the separator's :meth:`~object.__len__` mutates the original object.
+Patch by Bénédikt Tran.
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 338c71ad38f7aa..8a454aa48a0930 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -2664,7 +2664,13 @@ bytearray_hex_impl(PyByteArrayObject *self, PyObject
*sep, int bytes_per_sep)
{
char* argbuf = PyByteArray_AS_STRING(self);
Py_ssize_t arglen = PyByteArray_GET_SIZE(self);
- return _Py_strhex_with_sep(argbuf, arglen, sep, bytes_per_sep);
+ // Prevent 'self' from being freed if computing len(sep) mutates 'self'
+ // in _Py_strhex_with_sep().
+ // See: https://github.com/python/cpython/issues/143195.
+ self->ob_exports++;
+ PyObject *res = _Py_strhex_with_sep(argbuf, arglen, sep, bytes_per_sep);
+ self->ob_exports--;
+ return res;
}
static PyObject *
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index f1232f389210ea..2fd1d784b92ec8 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -2349,7 +2349,13 @@ memoryview_hex_impl(PyMemoryViewObject *self, PyObject
*sep,
CHECK_RELEASED(self);
if (MV_C_CONTIGUOUS(self->flags)) {
- return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
+ // Prevent 'self' from being freed if computing len(sep) mutates 'self'
+ // in _Py_strhex_with_sep().
+ // See: https://github.com/python/cpython/issues/143195.
+ self->exports++;
+ PyObject *ret = _Py_strhex_with_sep(src->buf, src->len, sep,
bytes_per_sep);
+ self->exports--;
+ return ret;
}
PyBytesWriter *writer = PyBytesWriter_Create(src->len);
_______________________________________________
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]