[Python-checkins] r75731 - in python/trunk: Lib/test/test_float.py Objects/floatobject.c

mark.dickinson python-checkins at python.org
Mon Oct 26 22:11:21 CET 2009


Author: mark.dickinson
Date: Mon Oct 26 22:11:20 2009
New Revision: 75731

Log:
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().


Modified:
   python/trunk/Lib/test/test_float.py
   python/trunk/Objects/floatobject.c

Modified: python/trunk/Lib/test/test_float.py
==============================================================================
--- python/trunk/Lib/test/test_float.py	(original)
+++ python/trunk/Lib/test/test_float.py	Mon Oct 26 22:11:20 2009
@@ -31,8 +31,6 @@
         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):

Modified: python/trunk/Objects/floatobject.c
==============================================================================
--- python/trunk/Objects/floatobject.c	(original)
+++ python/trunk/Objects/floatobject.c	Mon Oct 26 22:11:20 2009
@@ -181,9 +181,10 @@
 	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 @@
 	}
 #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 @@
 	/* 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


More information about the Python-checkins mailing list