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:
|
if test_support.have_unicode:
|
||||||
self.assertEqual(float(unicode(" 3.14 ")), 3.14)
|
self.assertEqual(float(unicode(" 3.14 ")), 3.14)
|
||||||
self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 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')
|
@test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
|
||||||
def test_float_with_comma(self):
|
def test_float_with_comma(self):
|
||||||
|
|
|
@ -181,9 +181,10 @@ PyFloat_FromString(PyObject *v, char **pend)
|
||||||
double x;
|
double x;
|
||||||
char buffer[256]; /* for errors */
|
char buffer[256]; /* for errors */
|
||||||
#ifdef Py_USING_UNICODE
|
#ifdef Py_USING_UNICODE
|
||||||
char s_buffer[256]; /* for objects convertible to a char buffer */
|
char *s_buffer = NULL;
|
||||||
#endif
|
#endif
|
||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
if (pend)
|
if (pend)
|
||||||
*pend = NULL;
|
*pend = NULL;
|
||||||
|
@ -193,23 +194,21 @@ PyFloat_FromString(PyObject *v, char **pend)
|
||||||
}
|
}
|
||||||
#ifdef Py_USING_UNICODE
|
#ifdef Py_USING_UNICODE
|
||||||
else if (PyUnicode_Check(v)) {
|
else if (PyUnicode_Check(v)) {
|
||||||
if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) {
|
s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1);
|
||||||
PyErr_SetString(PyExc_ValueError,
|
if (s_buffer == NULL)
|
||||||
"Unicode float() literal too long to convert");
|
return PyErr_NoMemory();
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
|
if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
|
||||||
PyUnicode_GET_SIZE(v),
|
PyUnicode_GET_SIZE(v),
|
||||||
s_buffer,
|
s_buffer,
|
||||||
NULL))
|
NULL))
|
||||||
return NULL;
|
goto error;
|
||||||
s = s_buffer;
|
s = s_buffer;
|
||||||
len = strlen(s);
|
len = strlen(s);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (PyObject_AsCharBuffer(v, &s, &len)) {
|
else if (PyObject_AsCharBuffer(v, &s, &len)) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"float() argument must be a string or a number");
|
"float() argument must be a string or a number");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
last = s + len;
|
last = s + len;
|
||||||
|
@ -219,36 +218,26 @@ PyFloat_FromString(PyObject *v, char **pend)
|
||||||
/* We don't care about overflow or underflow. If the platform
|
/* We don't care about overflow or underflow. If the platform
|
||||||
* supports them, infinities and signed zeroes (on underflow) are
|
* supports them, infinities and signed zeroes (on underflow) are
|
||||||
* fine. */
|
* fine. */
|
||||||
errno = 0;
|
x = PyOS_string_to_double(s, (char **)&end, NULL);
|
||||||
PyFPE_START_PROTECT("strtod", return NULL)
|
if (x == -1.0 && PyErr_Occurred())
|
||||||
x = PyOS_ascii_strtod(s, (char **)&end);
|
goto error;
|
||||||
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. */
|
|
||||||
while (Py_ISSPACE(*end))
|
while (Py_ISSPACE(*end))
|
||||||
end++;
|
end++;
|
||||||
if (end != last) {
|
if (end == last)
|
||||||
if (*end == '\0')
|
result = PyFloat_FromDouble(x);
|
||||||
PyErr_SetString(PyExc_ValueError,
|
else {
|
||||||
"null byte in argument for float()");
|
PyOS_snprintf(buffer, sizeof(buffer),
|
||||||
else {
|
"invalid literal for float(): %.200s", s);
|
||||||
PyOS_snprintf(buffer, sizeof(buffer),
|
PyErr_SetString(PyExc_ValueError, buffer);
|
||||||
"invalid literal for float(): %.200s", s);
|
result = NULL;
|
||||||
PyErr_SetString(PyExc_ValueError, buffer);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
return PyFloat_FromDouble(x);
|
|
||||||
|
error:
|
||||||
|
#ifdef Py_USING_UNICODE
|
||||||
|
if (s_buffer)
|
||||||
|
PyMem_FREE(s_buffer);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue