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
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.
--- /dev/null
+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.
{
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 *
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);