]> granicus.if.org Git - python/commitdiff
Issue #7117: Use PyOS_string_to_double instead of PyOS_ascii_strtod in
authorMark Dickinson <dickinsm@gmail.com>
Mon, 26 Oct 2009 21:11:20 +0000 (21:11 +0000)
committerMark Dickinson <dickinsm@gmail.com>
Mon, 26 Oct 2009 21:11:20 +0000 (21:11 +0000)
floatobject.c.  Also, remove limitation on length of unicode inputs to
float().

Lib/test/test_float.py
Objects/floatobject.c

index 844a6495503e113a0574562cc9c19c97cfee3dac..9d0c69d4c063cbdcb303e06f151f42574e5f58a1 100644 (file)
@@ -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):
index 1bfc57edfb4e87f0faba9a6c01080ebc8a33a635..28b2004bce2ee6c4867b06193e7c44705a86e407 100644 (file)
@@ -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