diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-05-11 16:09:39 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-05-11 16:09:39 (GMT) |
commit | ce05717daa31be8e2bb93e405f8f37fc8d0fe233 (patch) | |
tree | 6dee3e221234535df1dfac30be8b64b2e6488763 /Objects | |
parent | fd9258d0dd959cd15abfef8decb9021e061e425d (diff) | |
download | cpython-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.c | 54 |
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); |