summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-05-11 16:09:39 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-05-11 16:09:39 (GMT)
commitce05717daa31be8e2bb93e405f8f37fc8d0fe233 (patch)
tree6dee3e221234535df1dfac30be8b64b2e6488763 /Objects
parentfd9258d0dd959cd15abfef8decb9021e061e425d (diff)
downloadcpython-ce05717daa31be8e2bb93e405f8f37fc8d0fe233.zip
cpython-ce05717daa31be8e2bb93e405f8f37fc8d0fe233.tar.gz
cpython-ce05717daa31be8e2bb93e405f8f37fc8d0fe233.tar.bz2
Merged revisions 72564 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r72564 | mark.dickinson | 2009-05-11 16:33:08 +0100 (Mon, 11 May 2009) | 2 lines Issue #5981: Fix some float.fromhex bugs related to inf and nan handling. ........
Diffstat (limited to 'Objects')
-rw-r--r--Objects/floatobject.c54
1 files changed, 37 insertions, 17 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 4f041f4..2d00c16 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1263,6 +1263,20 @@ Return a hexadecimal representation of a floating-point number.\n\
>>> 3.14159.hex()\n\
'0x1.921f9f01b866ep+1'");
+/* Case-insensitive string match used for nan and inf detection. t should be
+ lower-case and null-terminated. Return a nonzero result if the first
+ strlen(t) characters of s match t and 0 otherwise. */
+
+static int
+case_insensitive_match(const char *s, const char *t)
+{
+ while(*t && tolower(*s) == *t) {
+ s++;
+ t++;
+ }
+ return *t ? 0 : 1;
+}
+
/* Convert a hexadecimal string to a float. */
static PyObject *
@@ -1329,7 +1343,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
********************/
/* leading whitespace and optional sign */
- while (isspace(*s))
+ while (*s && isspace(Py_CHARMASK(*s)))
s++;
if (*s == '-') {
s++;
@@ -1339,13 +1353,20 @@ float_fromhex(PyObject *cls, PyObject *arg)
s++;
/* infinities and nans */
- if (PyOS_strnicmp(s, "nan", 4) == 0) {
- x = Py_NAN;
+ if (*s == 'i' || *s == 'I') {
+ if (!case_insensitive_match(s+1, "nf"))
+ goto parse_error;
+ s += 3;
+ x = Py_HUGE_VAL;
+ if (case_insensitive_match(s, "inity"))
+ s += 5;
goto finished;
}
- if (PyOS_strnicmp(s, "inf", 4) == 0 ||
- PyOS_strnicmp(s, "infinity", 9) == 0) {
- x = sign*Py_HUGE_VAL;
+ if (*s == 'n' || *s == 'N') {
+ if (!case_insensitive_match(s+1, "an"))
+ goto parse_error;
+ s += 3;
+ x = Py_NAN;
goto finished;
}
@@ -1398,12 +1419,6 @@ float_fromhex(PyObject *cls, PyObject *arg)
else
exp = 0;
- /* optional trailing whitespace leading to the end of the string */
- while (isspace(*s))
- s++;
- if (s != s_end)
- goto parse_error;
-
/* for 0 <= j < ndigits, HEX_DIGIT(j) gives the jth most significant digit */
#define HEX_DIGIT(j) hex_from_char(*((j) < fdigits ? \
coeff_end-(j) : \
@@ -1417,7 +1432,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
while (ndigits > 0 && HEX_DIGIT(ndigits-1) == 0)
ndigits--;
if (ndigits == 0 || exp < LONG_MIN/2) {
- x = sign * 0.0;
+ x = 0.0;
goto finished;
}
if (exp > LONG_MAX/2)
@@ -1433,7 +1448,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
/* catch almost all nonextreme cases of overflow and underflow here */
if (top_exp < DBL_MIN_EXP - DBL_MANT_DIG) {
- x = sign * 0.0;
+ x = 0.0;
goto finished;
}
if (top_exp > DBL_MAX_EXP)
@@ -1448,7 +1463,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
/* no rounding required */
for (i = ndigits-1; i >= 0; i--)
x = 16.0*x + HEX_DIGIT(i);
- x = sign * ldexp(x, (int)(exp));
+ x = ldexp(x, (int)(exp));
goto finished;
}
/* rounding required. key_digit is the index of the hex digit
@@ -1482,10 +1497,15 @@ float_fromhex(PyObject *cls, PyObject *arg)
goto overflow_error;
}
}
- x = sign * ldexp(x, (int)(exp+4*key_digit));
+ x = ldexp(x, (int)(exp+4*key_digit));
finished:
- result_as_float = Py_BuildValue("(d)", x);
+ /* optional trailing whitespace leading to the end of the string */
+ while (*s && isspace(Py_CHARMASK(*s)))
+ s++;
+ if (s != s_end)
+ goto parse_error;
+ result_as_float = Py_BuildValue("(d)", sign * x);
if (result_as_float == NULL)
return NULL;
result = PyObject_CallObject(cls, result_as_float);