https://github.com/python/cpython/commit/66df30d15c9052785ed6463663e70d38107a9edf commit: 66df30d15c9052785ed6463663e70d38107a9edf branch: 3.14 author: Miss Islington (bot) <[email protected]> committer: vstinner <[email protected]> date: 2026-10-04T00:20:09Z summary:
[3.14] gh-158583: Fix uninitialized memory read in bytes.fromhex() (GH-158584) (#158692) gh-158583: Fix uninitialized memory read in bytes.fromhex() (GH-158584) (cherry picked from commit 9d22a5334bd5273962adceeb697a1337e9a0ca21) Co-authored-by: Victor Stinner <[email protected]> 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 d9d65b223f033ab..e7da6630c1f423f 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 000000000000000..c94fcc58add88c5 --- /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 e22139752540801..aafbe398417898a 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); } _______________________________________________ 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]
