[Python-checkins] CVS: python/dist/src/Objects floatobject.c,2.70,2.71
Tim Peters
python-dev@python.org
Fri, 22 Sep 2000 20:39:20 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory slayer.i.sourceforge.net:/tmp/cvs-serv9812/python/dist/src/objects
Modified Files:
floatobject.c
Log Message:
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.
Index: floatobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v
retrieving revision 2.70
retrieving revision 2.71
diff -C2 -r2.70 -r2.71
*** floatobject.c 2000/09/16 03:54:24 2.70
--- floatobject.c 2000/09/23 03:39:17 2.71
***************
*** 118,131 ****
}
PyObject *
PyFloat_FromString(PyObject *v, char **pend)
{
- extern double strtod(const char *, char **);
const char *s, *last, *end;
double x;
! char buffer[256]; /* For errors */
! char s_buffer[256];
int len;
if (PyString_Check(v)) {
s = PyString_AS_STRING(v);
--- 118,148 ----
}
+ /**************************************************************************
+ 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 *
PyFloat_FromString(PyObject *v, char **pend)
{
const char *s, *last, *end;
double x;
! char buffer[256]; /* for errors */
! char s_buffer[256]; /* for objects convertible to a char buffer */
int len;
+ if (pend)
+ *pend = NULL;
if (PyString_Check(v)) {
s = PyString_AS_STRING(v);
***************
*** 135,142 ****
if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) {
PyErr_SetString(PyExc_ValueError,
! "float() literal too large to convert");
return NULL;
}
! if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
PyUnicode_GET_SIZE(v),
s_buffer,
--- 152,159 ----
if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) {
PyErr_SetString(PyExc_ValueError,
! "Unicode float() literal too long to convert");
return NULL;
}
! if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
PyUnicode_GET_SIZE(v),
s_buffer,
***************
*** 155,170 ****
while (*s && isspace(Py_CHARMASK(*s)))
s++;
! if (s[0] == '\0') {
PyErr_SetString(PyExc_ValueError, "empty string for float()");
return NULL;
}
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
! byte at the end of the string, when the input is inf(inity) */
if (end > last)
end = last;
while (*end && isspace(Py_CHARMASK(*end)))
end++;
--- 172,199 ----
while (*s && isspace(Py_CHARMASK(*s)))
s++;
! if (*s == '\0') {
PyErr_SetString(PyExc_ValueError, "empty string for float()");
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;
/* 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). */
if (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)))
end++;
***************
*** 179,189 ****
return NULL;
}
! else if (errno != 0) {
! sprintf(buffer, "float() literal too large: %.200s", s);
! PyErr_SetString(PyExc_ValueError, buffer);
! return NULL;
}
- if (pend)
- *pend = (char *)end;
return PyFloat_FromDouble(x);
}
--- 208,217 ----
return NULL;
}
! if (x == 0.0) {
! /* See above -- may have been strtod being anal
! about denorms. */
! x = atof(s);
! errno = 0; /* whether atof ever set errno is undefined */
}
return PyFloat_FromDouble(x);
}