https://github.com/python/cpython/commit/9d22a5334bd5273962adceeb697a1337e9a0ca21
commit: 9d22a5334bd5273962adceeb697a1337e9a0ca21
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-10-03T23:51:37Z
summary:
gh-158583: Fix uninitialized memory read in bytes.fromhex() (#158584)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-10-03-16-14-26.gh-issue-158583.7EUMvS.rst
M Lib/test/test_bytes.py
M Objects/bytesobject.c
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index ea0a54dd5e1d35..0f2eec38631213 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -518,6 +518,15 @@ def test_fromhex(self):
self.type2test.fromhex(data)
self.assertIn('at position %s' % pos, str(cm.exception))
+ # gh-158583: Check for out of bounds reads (uninitialized bytes).
+ # Create an array from a list to not overallocate.
+ a = array.array('B', list(b'1234 ')) # Py_ISSPACE() loop
+ self.assertEqual(self.type2test.fromhex(a), b'\x12\x34')
+
+ a = array.array('B', list(b'12345')) # Missing second digit
+ with self.assertRaises(ValueError):
+ self.type2test.fromhex(a)
+
def test_hex(self):
self.assertRaises(TypeError, self.type2test.hex)
self.assertRaises(TypeError, self.type2test.hex, 1)
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-03-16-14-26.gh-issue-158583.7EUMvS.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-03-16-14-26.gh-issue-158583.7EUMvS.rst
new file mode 100644
index 00000000000000..c94fcc58add88c
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-03-16-14-26.gh-issue-158583.7EUMvS.rst
@@ -0,0 +1,2 @@
+:meth:`bytes.fromhex` and :meth:`bytearray.fromhex`: Fix uninitialized
+memory read. Patch by Victor Stinner.
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index ac3a3340ec3201..e7bc465a87f4a0 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2702,9 +2702,10 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray)
if (Py_ISSPACE(*str)) {
do {
str++;
+ if (str >= end) {
+ goto done;
+ }
} while (Py_ISSPACE(*str));
- if (str >= end)
- break;
}
top = _PyLong_DigitValue[*str];
@@ -2712,16 +2713,16 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray)
invalid_char = str - start;
goto error;
}
+
str++;
+ if (str >= end) {
+ invalid_char = -1;
+ goto error;
+ }
bot = _PyLong_DigitValue[*str];
if (bot >= 16) {
- /* Check if we had a second digit */
- if (str >= end){
- invalid_char = -1;
- } else {
- invalid_char = str - start;
- }
+ invalid_char = str - start;
goto error;
}
str++;
@@ -2729,6 +2730,7 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray)
*buf++ = (unsigned char)((top << 4) + bot);
}
+ done:
if (view.obj != NULL) {
PyBuffer_Release(&view);
}
_______________________________________________
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]