diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-05-01 11:42:00 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-05-01 11:42:00 (GMT) |
commit | f489caf5daa2b0f3a1bd951b585c834aab1a54c6 (patch) | |
tree | f57e0339acc0f5b702743d438738ad2f0d2aeba7 /Objects | |
parent | fb526ac34af13116733fcd0a306016e253d90c08 (diff) | |
download | cpython-f489caf5daa2b0f3a1bd951b585c834aab1a54c6.zip cpython-f489caf5daa2b0f3a1bd951b585c834aab1a54c6.tar.gz cpython-f489caf5daa2b0f3a1bd951b585c834aab1a54c6.tar.bz2 |
Issue #5859: Remove use of fixed-length buffers for float formatting
in unicodeobject.c and the fallback version of PyOS_double_to_string.
As a result, operations like '%.120e' % 12.34 no longer raise an
exception.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/unicodeobject.c | 84 |
1 files changed, 18 insertions, 66 deletions
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 3cea899..31b9a73 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -8792,73 +8792,30 @@ getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx) return NULL; } -static void -strtounicode(Py_UNICODE *buffer, const char *charbuffer, Py_ssize_t len) -{ - register Py_ssize_t i; - for (i = len - 1; i >= 0; i--) - buffer[i] = (Py_UNICODE) charbuffer[i]; -} +/* Returns a new reference to a PyUnicode object, or NULL on failure. */ -static int -formatfloat(Py_UNICODE *buf, - size_t buflen, - int flags, - int prec, - int type, - PyObject *v) -{ - /* eric.smith: To minimize disturbances in PyUnicode_Format (the - only caller of this routine), I'm going to keep the existing - API to this function. That means that we'll allocate memory and - then copy back into the supplied buffer. But that's better than - all of the changes that would be required in PyUnicode_Format - because it does lots of memory management tricks. */ - - char* p = NULL; - int result = -1; +static PyObject * +formatfloat(PyObject *v, int flags, int prec, int type) +{ + char *p; + PyObject *result; double x; - Py_ssize_t len; x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) - goto done; + return NULL; + if (prec < 0) prec = 6; - /* make sure that the decimal representation of precision really does - need at most 10 digits: platforms with sizeof(int) == 8 exist! */ - if (prec > 0x7fffffffL) { - PyErr_SetString(PyExc_OverflowError, - "outrageously large precision " - "for formatted float"); - goto done; - } - if (type == 'f' && fabs(x) >= 1e50) type = 'g'; - if (((type == 'g' || type == 'G') && - buflen <= (size_t)10 + (size_t)prec) || - ((type == 'f' || type == 'F') && - buflen <= (size_t)53 + (size_t)prec)) { - PyErr_SetString(PyExc_OverflowError, - "formatted float is too long (precision too large?)"); - goto done; - } - p = PyOS_double_to_string(x, type, prec, (flags & F_ALT) ? Py_DTSF_ALT : 0, NULL); - len = strlen(p); - if (len+1 >= buflen) { - /* Caller supplied buffer is not large enough. */ - PyErr_NoMemory(); - goto done; - } - strtounicode(buf, p, len); - result = Py_SAFE_DOWNCAST(len, Py_ssize_t, int); - -done: + if (p == NULL) + return NULL; + result = PyUnicode_FromStringAndSize(p, strlen(p)); PyMem_Free(p); return result; } @@ -8940,14 +8897,9 @@ formatchar(Py_UNICODE *buf, } /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) - - FORMATBUFLEN is the length of the buffer in which the floats, ints, & - chars are formatted. XXX This is a magic number. Each formatting - routine does bounds checking to ensure no overflow, but a better - solution may be to malloc a buffer of appropriate size for each - format. For now, the current solution is sufficient. + FORMATBUFLEN is the length of the buffer in which chars are formatted. */ -#define FORMATBUFLEN (size_t)120 +#define FORMATBUFLEN (size_t)10 PyObject *PyUnicode_Format(PyObject *format, PyObject *args) @@ -9012,7 +8964,7 @@ PyObject *PyUnicode_Format(PyObject *format, Py_UNICODE *pbuf; Py_UNICODE sign; Py_ssize_t len; - Py_UNICODE formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */ + Py_UNICODE formatbuf[FORMATBUFLEN]; /* For formatchar() */ fmt++; if (*fmt == '(') { @@ -9257,11 +9209,11 @@ PyObject *PyUnicode_Format(PyObject *format, case 'F': case 'g': case 'G': - pbuf = formatbuf; - len = formatfloat(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), - flags, prec, c, v); - if (len < 0) + temp = formatfloat(v, flags, prec, c); + if (!temp) goto onError; + pbuf = PyUnicode_AS_UNICODE(temp); + len = PyUnicode_GET_SIZE(temp); sign = 1; if (flags & F_ZERO) fill = '0'; |