mirror of https://github.com/python/cpython
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:
parent
3e1eb0f715
commit
8568b19850
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue