Kaydet (Commit) 2be161dc authored tarafından Guido van Rossum's avatar Guido van Rossum

Make tset_float pass. float(<unicode>) was never very good -- it used

a fixed-length buffer of 256 bytes.
üst a28c291e
...@@ -39,15 +39,15 @@ class FormatFunctionsTestCase(unittest.TestCase): ...@@ -39,15 +39,15 @@ class FormatFunctionsTestCase(unittest.TestCase):
self.assertRaises(ValueError, float.__setformat__, self.assertRaises(ValueError, float.__setformat__,
'chicken', 'unknown') 'chicken', 'unknown')
BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00' BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF)) LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00' BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN)) LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
BE_FLOAT_INF = '\x7f\x80\x00\x00' BE_FLOAT_INF = b'\x7f\x80\x00\x00'
LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF)) LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
BE_FLOAT_NAN = '\x7f\xc0\x00\x00' BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN)) LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
# on non-IEEE platforms, attempting to unpack a bit pattern # on non-IEEE platforms, attempting to unpack a bit pattern
# representing an infinity or a NaN should raise an exception. # representing an infinity or a NaN should raise an exception.
......
...@@ -68,19 +68,18 @@ PyFloat_FromString(PyObject *v) ...@@ -68,19 +68,18 @@ PyFloat_FromString(PyObject *v)
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]; /* for objects convertible to a char buffer */ char *s_buffer = NULL;
Py_ssize_t len; Py_ssize_t len;
PyObject *result = 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);
} }
else if (PyUnicode_Check(v)) { else if (PyUnicode_Check(v)) {
if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) { s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1);
PyErr_SetString(PyExc_ValueError, if (s_buffer == NULL)
"Unicode float() literal too long to convert"); return PyErr_NoMemory();
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,
...@@ -100,7 +99,7 @@ PyFloat_FromString(PyObject *v) ...@@ -100,7 +99,7 @@ PyFloat_FromString(PyObject *v)
s++; s++;
if (*s == '\0') { if (*s == '\0') {
PyErr_SetString(PyExc_ValueError, "empty string for float()"); PyErr_SetString(PyExc_ValueError, "empty string for float()");
return NULL; goto error;
} }
/* We don't care about overflow or underflow. If the platform supports /* We don't care about overflow or underflow. If the platform supports
* them, infinities and signed zeroes (on underflow) are fine. * them, infinities and signed zeroes (on underflow) are fine.
...@@ -109,7 +108,7 @@ PyFloat_FromString(PyObject *v) ...@@ -109,7 +108,7 @@ PyFloat_FromString(PyObject *v)
* whether strtod sets errno on underflow is not defined, so we can't * whether strtod sets errno on underflow is not defined, so we can't
* key off errno. * key off errno.
*/ */
PyFPE_START_PROTECT("strtod", return NULL) PyFPE_START_PROTECT("strtod", goto error)
x = PyOS_ascii_strtod(s, (char **)&end); x = PyOS_ascii_strtod(s, (char **)&end);
PyFPE_END_PROTECT(x) PyFPE_END_PROTECT(x)
errno = 0; errno = 0;
...@@ -121,7 +120,7 @@ PyFloat_FromString(PyObject *v) ...@@ -121,7 +120,7 @@ PyFloat_FromString(PyObject *v)
PyOS_snprintf(buffer, sizeof(buffer), PyOS_snprintf(buffer, sizeof(buffer),
"invalid literal for float(): %.200s", s); "invalid literal for float(): %.200s", s);
PyErr_SetString(PyExc_ValueError, buffer); PyErr_SetString(PyExc_ValueError, buffer);
return NULL; goto error;
} }
/* Since end != s, the platform made *some* kind of sense out /* Since end != s, the platform made *some* kind of sense out
of the input. Trust it. */ of the input. Trust it. */
...@@ -131,22 +130,26 @@ PyFloat_FromString(PyObject *v) ...@@ -131,22 +130,26 @@ PyFloat_FromString(PyObject *v)
PyOS_snprintf(buffer, sizeof(buffer), PyOS_snprintf(buffer, sizeof(buffer),
"invalid literal for float(): %.200s", s); "invalid literal for float(): %.200s", s);
PyErr_SetString(PyExc_ValueError, buffer); PyErr_SetString(PyExc_ValueError, buffer);
return NULL; goto error;
} }
else if (end != last) { else if (end != last) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"null byte in argument for float()"); "null byte in argument for float()");
return NULL; goto error;
} }
if (x == 0.0) { if (x == 0.0) {
/* See above -- may have been strtod being anal /* See above -- may have been strtod being anal
about denorms. */ about denorms. */
PyFPE_START_PROTECT("atof", return NULL) PyFPE_START_PROTECT("atof", goto error)
x = PyOS_ascii_atof(s); x = PyOS_ascii_atof(s);
PyFPE_END_PROTECT(x) PyFPE_END_PROTECT(x)
errno = 0; /* whether atof ever set errno is undefined */ 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 static void
...@@ -869,6 +872,11 @@ float_getformat(PyTypeObject *v, PyObject* arg) ...@@ -869,6 +872,11 @@ float_getformat(PyTypeObject *v, PyObject* arg)
char* s; char* s;
float_format_type r; float_format_type r;
if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString(arg, NULL);
if (arg == NULL)
return NULL;
}
if (!PyString_Check(arg)) { if (!PyString_Check(arg)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"__getformat__() argument must be string, not %.500s", "__getformat__() argument must be string, not %.500s",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment