From c04c7c5b72db5bcdde04982cad52212d3ddbc1a1 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 26 Oct 2009 22:28:14 +0000 Subject: [PATCH] Issue #7117: Use PyOS_string_to_double instead of PyOS_ascii_strtod in complexobject.c. Also remove length restriction on unicode inputs to the complex constructor. --- Lib/test/test_complex.py | 5 ++++- Misc/NEWS | 3 +++ Objects/complexobject.c | 45 ++++++++++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index f07a6b4b48e..a192ec45ac4 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -306,7 +306,6 @@ class ComplexTest(unittest.TestCase): self.assertRaises(ValueError, complex, "1+(2j)") self.assertRaises(ValueError, complex, "(1+2j)123") if test_support.have_unicode: - self.assertRaises(ValueError, complex, unicode("1"*500)) self.assertRaises(ValueError, complex, unicode("x")) self.assertRaises(ValueError, complex, "1j+2") self.assertRaises(ValueError, complex, "1e1ej") @@ -317,6 +316,10 @@ class ComplexTest(unittest.TestCase): self.assertRaises(ValueError, complex, "1.11.1j") self.assertRaises(ValueError, complex, "1e1.1j") + if test_support.have_unicode: + # check that complex accepts long unicode strings + self.assertEqual(type(complex(unicode("1"*500))), complex) + class EvilExc(Exception): pass diff --git a/Misc/NEWS b/Misc/NEWS index 368ed3e4af1..6d487145ac3 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1 Core and Builtins ----------------- +- Remove length limitation when constructing a complex number from a + unicode string. + - Removed _PyOS_double_to_string. Use PyOS_double_to_string instead. This is in preparation for (but not strictly related to) issue #7117, short float repr. diff --git a/Objects/complexobject.c b/Objects/complexobject.c index b976b6de520..f277b6625c1 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -921,7 +921,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) double x=0.0, y=0.0, z; int got_bracket=0; #ifdef Py_USING_UNICODE - char s_buffer[256]; + char *s_buffer = NULL; #endif Py_ssize_t len; @@ -931,16 +931,14 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(v)) { - if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) { - PyErr_SetString(PyExc_ValueError, - "complex() literal too large to convert"); - return NULL; - } + s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1); + if (s_buffer == NULL) + return PyErr_NoMemory(); if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), PyUnicode_GET_SIZE(v), s_buffer, NULL)) - return NULL; + goto error; s = s_buffer; len = strlen(s); } @@ -985,21 +983,26 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) */ /* first look for forms starting with */ - errno = 0; - z = PyOS_ascii_strtod(s, &end); - if (end == s && errno == ENOMEM) - return PyErr_NoMemory(); - + z = PyOS_string_to_double(s, &end, NULL); + if (z == -1.0 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_ValueError)) + PyErr_Clear(); + else + goto error; + } if (end != s) { /* all 4 forms starting with land here */ s = end; if (*s == '+' || *s == '-') { /* j | j */ x = z; - errno = 0; - y = PyOS_ascii_strtod(s, &end); - if (end == s && errno == ENOMEM) - return PyErr_NoMemory(); + y = PyOS_string_to_double(s, &end, NULL); + if (y == -1.0 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_ValueError)) + PyErr_Clear(); + else + goto error; + } if (end != s) /* j */ s = end; @@ -1053,11 +1056,21 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) if (s-start != len) goto parse_error; + +#ifdef Py_USING_UNICODE + if (s_buffer) + PyMem_FREE(s_buffer); +#endif return complex_subtype_from_doubles(type, x, y); parse_error: PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); + error: +#ifdef Py_USING_UNICODE + if (s_buffer) + PyMem_FREE(s_buffer); +#endif return NULL; }