diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index d9d65b223f033a..e7da6630c1f423 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -508,6 +508,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 e2213975254080..aafbe398417898 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2577,9 +2577,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]; @@ -2587,16 +2588,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++; @@ -2604,6 +2605,7 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray) *buf++ = (unsigned char)((top << 4) + bot); } + done: if (view.obj != NULL) { PyBuffer_Release(&view); }