From 85c0b8941f0c8ef3ed787c9d504712c6ad3eb5d3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 3 Oct 2017 14:13:44 +0300 Subject: [PATCH] bpo-31619: Fixed a ValueError when convert a string with large number of underscores (#3827) to integer with binary base. --- Lib/test/test_int.py | 8 ++++++++ .../2017-09-29-20-32-24.bpo-31619.6gQ1kv.rst | 2 ++ Objects/longobject.c | 8 ++++---- 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-09-29-20-32-24.bpo-31619.6gQ1kv.rst diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index 854117efd74..c048b712da8 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -508,5 +508,13 @@ def check(s, base=None): check('123\ud800') check('123\ud800', 10) + def test_issue31619(self): + self.assertEqual(int('1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1', 2), + 0b1010101010101010101010101010101) + self.assertEqual(int('1_2_3_4_5_6_7_0_1_2_3', 8), 0o12345670123) + self.assertEqual(int('1_2_3_4_5_6_7_8_9', 16), 0x123456789) + self.assertEqual(int('1_2_3_4_5_6_7', 32), 1144132807) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-29-20-32-24.bpo-31619.6gQ1kv.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-29-20-32-24.bpo-31619.6gQ1kv.rst new file mode 100644 index 00000000000..3efcc9d134d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-29-20-32-24.bpo-31619.6gQ1kv.rst @@ -0,0 +1,2 @@ +Fixed a ValueError when convert a string with large number of underscores +to integer with binary base. diff --git a/Objects/longobject.c b/Objects/longobject.c index 3b07585669e..c71b783cc03 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2057,15 +2057,15 @@ long_from_binary_base(const char **str, int base, PyLongObject **res) } *str = p; - /* n <- # of Python digits needed, = ceiling(n/PyLong_SHIFT). */ - n = digits * bits_per_char + PyLong_SHIFT - 1; - if (n / bits_per_char < p - start) { + /* n <- the number of Python digits needed, + = ceiling((digits * bits_per_char) / PyLong_SHIFT). */ + if (digits > (PY_SSIZE_T_MAX - (PyLong_SHIFT - 1)) / bits_per_char) { PyErr_SetString(PyExc_ValueError, "int string too large to convert"); *res = NULL; return 0; } - n = n / PyLong_SHIFT; + n = (digits * bits_per_char + PyLong_SHIFT - 1) / PyLong_SHIFT; z = _PyLong_New(n); if (z == NULL) { *res = NULL;