diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-10-26 21:11:20 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-10-26 21:11:20 (GMT) |
commit | 8568b198506b4d2ff3c0dc847f75989865b1e33e (patch) | |
tree | 9f9f6150ffc106bad3e2cd7e89b728ac2fddeb44 | |
parent | 3e1eb0f715b804f87fb1b0cf3ec6576d15ff0663 (diff) | |
download | cpython-8568b198506b4d2ff3c0dc847f75989865b1e33e.zip cpython-8568b198506b4d2ff3c0dc847f75989865b1e33e.tar.gz cpython-8568b198506b4d2ff3c0dc847f75989865b1e33e.tar.bz2 |
Issue #7117: Use PyOS_string_to_double instead of PyOS_ascii_strtod in
floatobject.c. Also, remove limitation on length of unicode inputs to
float().
-rw-r--r-- | Lib/test/test_float.py | 2 | ||||
-rw-r--r-- | Objects/floatobject.c | 59 |
2 files changed, 24 insertions, 37 deletions
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 844a649..9d0c69d 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -31,8 +31,6 @@ class GeneralFloatCases(unittest.TestCase): if test_support.have_unicode: self.assertEqual(float(unicode(" 3.14 ")), 3.14) self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14) - # Implementation limitation in PyFloat_FromString() - self.assertRaises(ValueError, float, unicode("1"*10000)) @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE') def test_float_with_comma(self): diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 1bfc57e..28b2004 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -181,9 +181,10 @@ PyFloat_FromString(PyObject *v, char **pend) double x; char buffer[256]; /* for errors */ #ifdef Py_USING_UNICODE - char s_buffer[256]; /* for objects convertible to a char buffer */ + char *s_buffer = NULL; #endif Py_ssize_t len; + PyObject *result = NULL; if (pend) *pend = NULL; @@ -193,23 +194,21 @@ PyFloat_FromString(PyObject *v, char **pend) } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(v)) { - if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) { - PyErr_SetString(PyExc_ValueError, - "Unicode float() literal too long 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); } #endif else if (PyObject_AsCharBuffer(v, &s, &len)) { PyErr_SetString(PyExc_TypeError, - "float() argument must be a string or a number"); + "float() argument must be a string or a number"); return NULL; } last = s + len; @@ -219,36 +218,26 @@ PyFloat_FromString(PyObject *v, char **pend) /* We don't care about overflow or underflow. If the platform * supports them, infinities and signed zeroes (on underflow) are * fine. */ - errno = 0; - PyFPE_START_PROTECT("strtod", return NULL) - x = PyOS_ascii_strtod(s, (char **)&end); - PyFPE_END_PROTECT(x) - if (end == s) { - if (errno == ENOMEM) - PyErr_NoMemory(); - else { - PyOS_snprintf(buffer, sizeof(buffer), - "invalid literal for float(): %.200s", s); - PyErr_SetString(PyExc_ValueError, buffer); - } - return NULL; - } - /* Since end != s, the platform made *some* kind of sense out - of the input. Trust it. */ + x = PyOS_string_to_double(s, (char **)&end, NULL); + if (x == -1.0 && PyErr_Occurred()) + goto error; while (Py_ISSPACE(*end)) end++; - if (end != last) { - if (*end == '\0') - PyErr_SetString(PyExc_ValueError, - "null byte in argument for float()"); - else { - PyOS_snprintf(buffer, sizeof(buffer), - "invalid literal for float(): %.200s", s); - PyErr_SetString(PyExc_ValueError, buffer); - } - return NULL; + if (end == last) + result = PyFloat_FromDouble(x); + else { + PyOS_snprintf(buffer, sizeof(buffer), + "invalid literal for float(): %.200s", s); + PyErr_SetString(PyExc_ValueError, buffer); + result = NULL; } - return PyFloat_FromDouble(x); + + error: +#ifdef Py_USING_UNICODE + if (s_buffer) + PyMem_FREE(s_buffer); +#endif + return result; } static void |