Issue #24802: Copy bytes-like objects to null-terminated buffers if necessary

This avoids possible buffer overreads when int(), float(), compile(), exec()
and eval() are passed bytes-like objects. Similar code is removed from the
complex() constructor, where it was not reachable.

Patch by John Leitch, Serhiy Storchaka and Martin Panter.
This commit is contained in:
Martin Panter 2015-11-07 02:32:21 +00:00
parent 9ad0aae656
commit eeb896c411
8 changed files with 161 additions and 36 deletions

View file

@ -530,6 +530,27 @@ if 1:
check_limit("a", "[0]")
check_limit("a", "*a")
def test_null_terminated(self):
# The source code is null-terminated internally, but bytes-like
# objects are accepted, which could be not terminated.
# Exception changed from TypeError to ValueError in 3.5
with self.assertRaisesRegex(Exception, "cannot contain null"):
compile("123\x00", "<dummy>", "eval")
with self.assertRaisesRegex(Exception, "cannot contain null"):
compile(memoryview(b"123\x00"), "<dummy>", "eval")
code = compile(memoryview(b"123\x00")[1:-1], "<dummy>", "eval")
self.assertEqual(eval(code), 23)
code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval")
self.assertEqual(eval(code), 23)
code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval")
self.assertEqual(eval(code), 23)
# Also test when eval() and exec() do the compilation step
self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23)
namespace = dict()
exec(memoryview(b"ax = 123")[1:-1], namespace)
self.assertEqual(namespace['x'], 12)
class TestStackSize(unittest.TestCase):
# These tests check that the computed stack size for a code object