From: Guido van Rossum Date: Tue, 15 May 2007 20:43:51 +0000 (+0000) Subject: Make tset_float pass. float() was never very good -- it used X-Git-Tag: v3.0a1~948 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2be161dcfa531b0e2f3f9887e198be59f477854e;p=python Make tset_float pass. float() was never very good -- it used a fixed-length buffer of 256 bytes. --- diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index fb47db8eb0..4f4cffd201 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -39,15 +39,15 @@ class FormatFunctionsTestCase(unittest.TestCase): self.assertRaises(ValueError, float.__setformat__, 'chicken', 'unknown') -BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00' -LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF)) -BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00' -LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN)) - -BE_FLOAT_INF = '\x7f\x80\x00\x00' -LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF)) -BE_FLOAT_NAN = '\x7f\xc0\x00\x00' -LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN)) +BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00' +LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF)) +BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00' +LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN)) + +BE_FLOAT_INF = b'\x7f\x80\x00\x00' +LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF)) +BE_FLOAT_NAN = b'\x7f\xc0\x00\x00' +LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN)) # on non-IEEE platforms, attempting to unpack a bit pattern # representing an infinity or a NaN should raise an exception. diff --git a/Objects/floatobject.c b/Objects/floatobject.c index b5fb9cfc55..fc6bedf7d9 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -68,19 +68,18 @@ PyFloat_FromString(PyObject *v) const char *s, *last, *end; double x; char buffer[256]; /* for errors */ - char s_buffer[256]; /* for objects convertible to a char buffer */ + char *s_buffer = NULL; Py_ssize_t len; + PyObject *result = NULL; if (PyString_Check(v)) { s = PyString_AS_STRING(v); len = PyString_GET_SIZE(v); } else if (PyUnicode_Check(v)) { - if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) { - PyErr_SetString(PyExc_ValueError, - "Unicode float() literal too long to convert"); - return NULL; - } + s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1); + if (s_buffer == NULL) + return PyErr_NoMemory(); if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), PyUnicode_GET_SIZE(v), s_buffer, @@ -100,7 +99,7 @@ PyFloat_FromString(PyObject *v) s++; if (*s == '\0') { PyErr_SetString(PyExc_ValueError, "empty string for float()"); - return NULL; + goto error; } /* We don't care about overflow or underflow. If the platform supports * them, infinities and signed zeroes (on underflow) are fine. @@ -109,7 +108,7 @@ PyFloat_FromString(PyObject *v) * whether strtod sets errno on underflow is not defined, so we can't * key off errno. */ - PyFPE_START_PROTECT("strtod", return NULL) + PyFPE_START_PROTECT("strtod", goto error) x = PyOS_ascii_strtod(s, (char **)&end); PyFPE_END_PROTECT(x) errno = 0; @@ -121,7 +120,7 @@ PyFloat_FromString(PyObject *v) PyOS_snprintf(buffer, sizeof(buffer), "invalid literal for float(): %.200s", s); PyErr_SetString(PyExc_ValueError, buffer); - return NULL; + goto error; } /* Since end != s, the platform made *some* kind of sense out of the input. Trust it. */ @@ -131,22 +130,26 @@ PyFloat_FromString(PyObject *v) PyOS_snprintf(buffer, sizeof(buffer), "invalid literal for float(): %.200s", s); PyErr_SetString(PyExc_ValueError, buffer); - return NULL; + goto error; } else if (end != last) { PyErr_SetString(PyExc_ValueError, "null byte in argument for float()"); - return NULL; + goto error; } if (x == 0.0) { /* See above -- may have been strtod being anal about denorms. */ - PyFPE_START_PROTECT("atof", return NULL) + PyFPE_START_PROTECT("atof", goto error) x = PyOS_ascii_atof(s); PyFPE_END_PROTECT(x) errno = 0; /* whether atof ever set errno is undefined */ } - return PyFloat_FromDouble(x); + result = PyFloat_FromDouble(x); + error: + if (s_buffer) + PyMem_FREE(s_buffer); + return result; } static void @@ -869,6 +872,11 @@ float_getformat(PyTypeObject *v, PyObject* arg) char* s; float_format_type r; + if (PyUnicode_Check(arg)) { + arg = _PyUnicode_AsDefaultEncodedString(arg, NULL); + if (arg == NULL) + return NULL; + } if (!PyString_Check(arg)) { PyErr_Format(PyExc_TypeError, "__getformat__() argument must be string, not %.500s",