summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorINADA Naoki <methane@users.noreply.github.com>2018-07-14 03:06:43 (GMT)
committerGitHub <noreply@github.com>2018-07-14 03:06:43 (GMT)
commit16dfca4d829e45f36e71bf43f83226659ce49315 (patch)
treef06c2f627ae2b4984d1c56ae97248b6eb5c51c38
parentcafaf0447b950fd4f59edd8cbde040c61ae528f8 (diff)
downloadcpython-16dfca4d829e45f36e71bf43f83226659ce49315.zip
cpython-16dfca4d829e45f36e71bf43f83226659ce49315.tar.gz
cpython-16dfca4d829e45f36e71bf43f83226659ce49315.tar.bz2
bpo-34087: Fix buffer overflow in int(s) and similar functions (GH-8274)
`_PyUnicode_TransformDecimalAndSpaceToASCII()` missed trailing NUL char. It caused buffer overflow in `_Py_string_to_number_with_underscores()`. This bug is introduced in 9b6c60cb.
-rw-r--r--Lib/test/test_complex.py3
-rw-r--r--Lib/test/test_float.py3
-rw-r--r--Lib/test/test_long.py4
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2018-07-13-22-09-55.bpo-34087.I1Bxfc.rst1
-rw-r--r--Objects/unicodeobject.c2
-rw-r--r--Python/pystrtod.c2
6 files changed, 15 insertions, 0 deletions
diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py
index 2d883c5..21c6eae 100644
--- a/Lib/test/test_complex.py
+++ b/Lib/test/test_complex.py
@@ -345,6 +345,9 @@ class ComplexTest(unittest.TestCase):
self.assertEqual(type(complex("1"*500)), complex)
# check whitespace processing
self.assertEqual(complex('\N{EM SPACE}(\N{EN SPACE}1+1j ) '), 1+1j)
+ # Invalid unicode string
+ # See bpo-34087
+ self.assertRaises(ValueError, complex, '\u3053\u3093\u306b\u3061\u306f')
class EvilExc(Exception):
pass
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
index 17174dd..06ea90c 100644
--- a/Lib/test/test_float.py
+++ b/Lib/test/test_float.py
@@ -60,6 +60,9 @@ class GeneralFloatCases(unittest.TestCase):
# extra long strings should not be a problem
float(b'.' + b'1'*1000)
float('.' + '1'*1000)
+ # Invalid unicode string
+ # See bpo-34087
+ self.assertRaises(ValueError, float, '\u3053\u3093\u306b\u3061\u306f')
def test_underscores(self):
for lit in VALID_UNDERSCORE_LITERALS:
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index cc48259..8472889 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -373,6 +373,10 @@ class LongTest(unittest.TestCase):
for base in invalid_bases:
self.assertRaises(ValueError, int, '42', base)
+ # Invalid unicode string
+ # See bpo-34087
+ self.assertRaises(ValueError, int, '\u3053\u3093\u306b\u3061\u306f')
+
def test_conversion(self):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-07-13-22-09-55.bpo-34087.I1Bxfc.rst b/Misc/NEWS.d/next/Core and Builtins/2018-07-13-22-09-55.bpo-34087.I1Bxfc.rst
new file mode 100644
index 0000000..5147395
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2018-07-13-22-09-55.bpo-34087.I1Bxfc.rst
@@ -0,0 +1 @@
+Fix buffer overflow while converting unicode to numeric values.
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 80d1bba..2b06f15 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -9072,6 +9072,7 @@ _PyUnicode_TransformDecimalAndSpaceToASCII(PyObject *unicode)
int decimal = Py_UNICODE_TODECIMAL(ch);
if (decimal < 0) {
out[i] = '?';
+ out[i+1] = '\0';
_PyUnicode_LENGTH(result) = i + 1;
break;
}
@@ -9079,6 +9080,7 @@ _PyUnicode_TransformDecimalAndSpaceToASCII(PyObject *unicode)
}
}
+ assert(_PyUnicode_CheckConsistency(result, 1));
return result;
}
diff --git a/Python/pystrtod.c b/Python/pystrtod.c
index 3546d44..461e8dc 100644
--- a/Python/pystrtod.c
+++ b/Python/pystrtod.c
@@ -391,6 +391,8 @@ _Py_string_to_number_with_underscores(
char *dup, *end;
PyObject *result;
+ assert(s[orig_len] == '\0');
+
if (strchr(s, '_') == NULL) {
return innerfunc(s, orig_len, arg);
}