Skip to content

Commit 36b7dc2

Browse files
vstinnermiss-islington
authored andcommitted
gh-158583: Fix uninitialized memory read in bytes.fromhex() (GH-158584)
(cherry picked from commit 9d22a53) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent e5ea201 commit 36b7dc2

3 files changed

Lines changed: 21 additions & 8 deletions

File tree

‎Lib/test/test_bytes.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,15 @@ def test_fromhex(self):
508508
self.type2test.fromhex(data)
509509
self.assertIn('at position %s' % pos, str(cm.exception))
510510

511+
# gh-158583: Check for out of bounds reads (uninitialized bytes).
512+
# Create an array from a list to not overallocate.
513+
a = array.array('B', list(b'1234 ')) # Py_ISSPACE() loop
514+
self.assertEqual(self.type2test.fromhex(a), b'\x12\x34')
515+
516+
a = array.array('B', list(b'12345')) # Missing second digit
517+
with self.assertRaises(ValueError):
518+
self.type2test.fromhex(a)
519+
511520
def test_hex(self):
512521
self.assertRaises(TypeError, self.type2test.hex)
513522
self.assertRaises(TypeError, self.type2test.hex, 1)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:meth:`bytes.fromhex` and :meth:`bytearray.fromhex`: Fix uninitialized
2+
memory read. Patch by Victor Stinner.

‎Objects/bytesobject.c‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,33 +2691,35 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray)
26912691
if (Py_ISSPACE(*str)) {
26922692
do {
26932693
str++;
2694+
if (str >= end) {
2695+
goto done;
2696+
}
26942697
} while (Py_ISSPACE(*str));
2695-
if (str >= end)
2696-
break;
26972698
}
26982699

26992700
top = _PyLong_DigitValue[*str];
27002701
if (top >= 16) {
27012702
invalid_char = str - start;
27022703
goto error;
27032704
}
2705+
27042706
str++;
2707+
if (str >= end) {
2708+
invalid_char = -1;
2709+
goto error;
2710+
}
27052711

27062712
bot = _PyLong_DigitValue[*str];
27072713
if (bot >= 16) {
2708-
/* Check if we had a second digit */
2709-
if (str >= end){
2710-
invalid_char = -1;
2711-
} else {
2712-
invalid_char = str - start;
2713-
}
2714+
invalid_char = str - start;
27142715
goto error;
27152716
}
27162717
str++;
27172718

27182719
*buf++ = (unsigned char)((top << 4) + bot);
27192720
}
27202721

2722+
done:
27212723
if (view.obj != NULL) {
27222724
PyBuffer_Release(&view);
27232725
}

0 commit comments

Comments
 (0)