mirror of https://github.com/python/cpython
Fix for SF bug 110624: float literals behave inconsistently.
I fixed the specific complaint but left the (many) large issues untouched. See the (very long) bug report discussion for why: http://sourceforge.net/bugs/?func=detailbug&group_id=5470&bug_id=110624 Note that while I left the interface to the undocumented public API function PyFloat_FromString alone, its 2nd argument is useless. From a comment block in the code: RED_FLAG 22-Sep-2000 tim PyFloat_FromString's pend argument is braindead. Prior to this RED_FLAG, 1. If v was a regular string, *pend was set to point to its terminating null byte. That's useless (the caller can find that without any help from this function!). 2. If v was a Unicode string, or an object convertible to a character buffer, *pend was set to point into stack trash (the auto temp vector holding the character buffer). That was downright dangerous. Since we can't change the interface of a public API function, pend is still supported but now *officially* useless: if pend is not NULL, *pend is set to NULL.
This commit is contained in:
parent
891150bdf2
commit
ef14d73b7a
|
@ -117,16 +117,33 @@ PyFloat_FromDouble(double fval)
|
||||||
return (PyObject *) op;
|
return (PyObject *) op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
RED_FLAG 22-Sep-2000 tim
|
||||||
|
PyFloat_FromString's pend argument is braindead. Prior to this RED_FLAG,
|
||||||
|
|
||||||
|
1. If v was a regular string, *pend was set to point to its terminating
|
||||||
|
null byte. That's useless (the caller can find that without any
|
||||||
|
help from this function!).
|
||||||
|
|
||||||
|
2. If v was a Unicode string, or an object convertible to a character
|
||||||
|
buffer, *pend was set to point into stack trash (the auto temp
|
||||||
|
vector holding the character buffer). That was downright dangerous.
|
||||||
|
|
||||||
|
Since we can't change the interface of a public API function, pend is
|
||||||
|
still supported but now *officially* useless: if pend is not NULL,
|
||||||
|
*pend is set to NULL.
|
||||||
|
**************************************************************************/
|
||||||
PyObject *
|
PyObject *
|
||||||
PyFloat_FromString(PyObject *v, char **pend)
|
PyFloat_FromString(PyObject *v, char **pend)
|
||||||
{
|
{
|
||||||
extern double strtod(const char *, char **);
|
|
||||||
const char *s, *last, *end;
|
const char *s, *last, *end;
|
||||||
double x;
|
double x;
|
||||||
char buffer[256]; /* For errors */
|
char buffer[256]; /* for errors */
|
||||||
char s_buffer[256];
|
char s_buffer[256]; /* for objects convertible to a char buffer */
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
if (pend)
|
||||||
|
*pend = NULL;
|
||||||
if (PyString_Check(v)) {
|
if (PyString_Check(v)) {
|
||||||
s = PyString_AS_STRING(v);
|
s = PyString_AS_STRING(v);
|
||||||
len = PyString_GET_SIZE(v);
|
len = PyString_GET_SIZE(v);
|
||||||
|
@ -134,10 +151,10 @@ PyFloat_FromString(PyObject *v, char **pend)
|
||||||
else if (PyUnicode_Check(v)) {
|
else if (PyUnicode_Check(v)) {
|
||||||
if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) {
|
if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"float() literal too large to convert");
|
"Unicode float() literal too long to convert");
|
||||||
return NULL;
|
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))
|
||||||
|
@ -154,18 +171,30 @@ PyFloat_FromString(PyObject *v, char **pend)
|
||||||
last = s + len;
|
last = s + len;
|
||||||
while (*s && isspace(Py_CHARMASK(*s)))
|
while (*s && isspace(Py_CHARMASK(*s)))
|
||||||
s++;
|
s++;
|
||||||
if (s[0] == '\0') {
|
if (*s == '\0') {
|
||||||
PyErr_SetString(PyExc_ValueError, "empty string for float()");
|
PyErr_SetString(PyExc_ValueError, "empty string for float()");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* We don't care about overflow or underflow. If the platform supports
|
||||||
|
* them, infinities and signed zeroes (on underflow) are fine.
|
||||||
|
* However, strtod can return 0 for denormalized numbers, where atof
|
||||||
|
* does not. So (alas!) we special-case a zero result. Note that
|
||||||
|
* whether strtod sets errno on underflow is not defined, so we can't
|
||||||
|
* key off errno.
|
||||||
|
*/
|
||||||
|
x = strtod(s, (char **)&end);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
PyFPE_START_PROTECT("PyFloat_FromString", return 0)
|
|
||||||
x = strtod((char *)s, (char **)&end);
|
|
||||||
PyFPE_END_PROTECT(x)
|
|
||||||
/* Believe it or not, Solaris 2.6 can move end *beyond* the null
|
/* Believe it or not, Solaris 2.6 can move end *beyond* the null
|
||||||
byte at the end of the string, when the input is inf(inity) */
|
byte at the end of the string, when the input is inf(inity). */
|
||||||
if (end > last)
|
if (end > last)
|
||||||
end = last;
|
end = last;
|
||||||
|
if (end == s) {
|
||||||
|
sprintf(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 (*end && isspace(Py_CHARMASK(*end)))
|
while (*end && isspace(Py_CHARMASK(*end)))
|
||||||
end++;
|
end++;
|
||||||
if (*end != '\0') {
|
if (*end != '\0') {
|
||||||
|
@ -178,13 +207,12 @@ PyFloat_FromString(PyObject *v, char **pend)
|
||||||
"null byte in argument for float()");
|
"null byte in argument for float()");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (errno != 0) {
|
if (x == 0.0) {
|
||||||
sprintf(buffer, "float() literal too large: %.200s", s);
|
/* See above -- may have been strtod being anal
|
||||||
PyErr_SetString(PyExc_ValueError, buffer);
|
about denorms. */
|
||||||
return NULL;
|
x = atof(s);
|
||||||
|
errno = 0; /* whether atof ever set errno is undefined */
|
||||||
}
|
}
|
||||||
if (pend)
|
|
||||||
*pend = (char *)end;
|
|
||||||
return PyFloat_FromDouble(x);
|
return PyFloat_FromDouble(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue