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().
This commit is contained in:
Mark Dickinson 2009-10-26 21:11:20 +00:00
parent 3e1eb0f715
commit 8568b19850
2 changed files with 24 additions and 37 deletions

View 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):

View 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