Why was the change that occurred in revision 2.31 reverted? Accident? The change log said: Jack Jansen: Use include "" instead of <>; and staticforward declarations On Fri, Jun 30 2000 "M.-A. Lemburg" wrote:
Update of /cvsroot/python/python/dist/src/Objects In directory slayer.i.sourceforge.net:/tmp/cvs-serv25442/Objects
Modified Files: unicodeobject.c Log Message: Marc-Andre Lemburg <mal@lemburg.com>: New buffer overflow checks for formatting strings.
By Trent Mick.
Index: unicodeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v retrieving revision 2.31 retrieving revision 2.32 diff -C2 -r2.31 -r2.32 *** unicodeobject.c 2000/06/29 00:06:39 2.31 --- unicodeobject.c 2000/06/30 10:29:57 2.32 *************** *** 67,71 **** #include "mymath.h" #include "unicodeobject.h" ! #include "ucnhash.h"
#if defined(HAVE_LIMITS_H) --- 67,71 ---- #include "mymath.h" #include "unicodeobject.h" ! #include <ucnhash.h>
#if defined(HAVE_LIMITS_H) *************** *** 1245,1249 **** ucnFallthrough: /* fall through on purpose */ ! default: *p++ = '\\'; *p++ = (unsigned char)s[-1]; --- 1245,1249 ---- ucnFallthrough: /* fall through on purpose */ ! default: *p++ = '\\'; *p++ = (unsigned char)s[-1]; *************** *** 1252,1256 **** } if (_PyUnicode_Resize(v, (int)(p - buf))) ! goto onError; return (PyObject *)v;
--- 1252,1256 ---- } if (_PyUnicode_Resize(v, (int)(p - buf))) ! goto onError; return (PyObject *)v;
*************** *** 4374,4377 **** --- 4374,4378 ---- static int formatfloat(Py_UNICODE *buf, + size_t buflen, int flags, int prec, *************** *** 4379,4382 **** --- 4380,4385 ---- PyObject *v) { + /* fmt = '%#.' + `prec` + `type` + worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/ char fmt[20]; double x; *************** *** 4387,4395 **** if (prec < 0) prec = 6; - if (prec > 50) - prec = 50; /* Arbitrary limitation */ if (type == 'f' && (fabs(x) / 1e25) >= 1e25) type = 'g'; sprintf(fmt, "%%%s.%d%c", (flags & F_ALT) ? "#" : "", prec, type); return usprintf(buf, fmt, x); } --- 4390,4408 ---- if (prec < 0) prec = 6; if (type == 'f' && (fabs(x) / 1e25) >= 1e25) type = 'g'; sprintf(fmt, "%%%s.%d%c", (flags & F_ALT) ? "#" : "", prec, type); + /* worst case length calc to ensure no buffer overrun: + fmt = %#.<prec>g + buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp + for any double rep.) + len = 1 + prec + 1 + 2 + 5 = 9 + prec + If prec=0 the effective precision is 1 (the leading digit is + always given), therefore increase by one to 10+prec. */ + if (buflen <= (size_t)10 + (size_t)prec) { + PyErr_SetString(PyExc_OverflowError, + "formatted float is too long (precision too long?)"); + return -1; + } return usprintf(buf, fmt, x); } *************** *** 4397,4400 **** --- 4410,4414 ---- static int formatint(Py_UNICODE *buf, + size_t buflen, int flags, int prec, *************** *** 4402,4405 **** --- 4416,4421 ---- PyObject *v) { + /* fmt = '%#.' + `prec` + 'l' + `type` + worst case length = 3 + 10 (len of INT_MAX) + 1 + 1 = 15 (use 20)*/ char fmt[20]; long x; *************** *** 4410,4413 **** --- 4426,4436 ---- if (prec < 0) prec = 1; + /* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec,len(x in octal)) + worst case buf = '0x' + [0-9]*prec, where prec >= 11 */ + if (buflen <= 13 || buflen <= (size_t)2+(size_t)prec) { + PyErr_SetString(PyExc_OverflowError, + "formatted integer is too long (precision too long?)"); + return -1; + } sprintf(fmt, "%%%s.%dl%c", (flags & F_ALT) ? "#" : "", prec, type); return usprintf(buf, fmt, x); *************** *** 4416,4421 **** static int formatchar(Py_UNICODE *buf, ! PyObject *v) { if (PyUnicode_Check(v)) { if (PyUnicode_GET_SIZE(v) != 1) --- 4439,4446 ---- static int formatchar(Py_UNICODE *buf, ! size_t buflen, ! PyObject *v) { + /* presume that the buffer is at least 2 characters long */ if (PyUnicode_Check(v)) { if (PyUnicode_GET_SIZE(v) != 1) *************** *** 4447,4450 **** --- 4472,4485 ---- }
+ /* 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. + */ + #define FORMATBUFLEN (size_t)120 + PyObject *PyUnicode_Format(PyObject *format, PyObject *args) *************** *** 4506,4513 **** PyObject *v = NULL; PyObject *temp = NULL; ! Py_UNICODE *buf; Py_UNICODE sign; int len; ! Py_UNICODE tmpbuf[120]; /* For format{float,int,char}() */
fmt++; --- 4541,4548 ---- PyObject *v = NULL; PyObject *temp = NULL; ! Py_UNICODE *pbuf; Py_UNICODE sign; int len; ! Py_UNICODE formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
fmt++; *************** *** 4659,4664 ****
case '%': ! buf = tmpbuf; ! buf[0] = '%'; len = 1; break; --- 4694,4700 ----
case '%': ! pbuf = formatbuf; ! /* presume that buffer length is at least 1 */ ! pbuf[0] = '%'; len = 1; break; *************** *** 4696,4700 **** goto onError; } ! buf = PyUnicode_AS_UNICODE(temp); len = PyUnicode_GET_SIZE(temp); if (prec >= 0 && len > prec) --- 4732,4736 ---- goto onError; } ! pbuf = PyUnicode_AS_UNICODE(temp); len = PyUnicode_GET_SIZE(temp); if (prec >= 0 && len > prec) *************** *** 4710,4715 **** if (c == 'i') c = 'd'; ! buf = tmpbuf; ! len = formatint(buf, flags, prec, c, v); if (len < 0) goto onError; --- 4746,4752 ---- if (c == 'i') c = 'd'; ! pbuf = formatbuf; ! len = formatint(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), ! flags, prec, c, v); if (len < 0) goto onError; *************** *** 4719,4725 **** if ((flags&F_ALT) && (c == 'x' || c == 'X') && ! buf[0] == '0' && buf[1] == c) { ! *res++ = *buf++; ! *res++ = *buf++; rescnt -= 2; len -= 2; --- 4756,4762 ---- if ((flags&F_ALT) && (c == 'x' || c == 'X') && ! pbuf[0] == '0' && pbuf[1] == c) { ! *res++ = *pbuf++; ! *res++ = *pbuf++; rescnt -= 2; len -= 2; *************** *** 4736,4741 **** case 'g': case 'G': ! buf = tmpbuf; ! len = formatfloat(buf, flags, prec, c, v); if (len < 0) goto onError; --- 4773,4779 ---- case 'g': case 'G': ! pbuf = formatbuf; ! len = formatfloat(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), ! flags, prec, c, v); if (len < 0) goto onError; *************** *** 4746,4751 ****
case 'c': ! buf = tmpbuf; ! len = formatchar(buf, v); if (len < 0) goto onError; --- 4784,4789 ----
case 'c': ! pbuf = formatbuf; ! len = formatchar(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), v); if (len < 0) goto onError; *************** *** 4759,4764 **** } if (sign) { ! if (*buf == '-' || *buf == '+') { ! sign = *buf++; len--; } --- 4797,4802 ---- } if (sign) { ! if (*pbuf == '-' || *pbuf == '+') { ! sign = *pbuf++; len--; } *************** *** 4796,4800 **** if (sign && fill == ' ') *res++ = sign; ! memcpy(res, buf, len * sizeof(Py_UNICODE)); res += len; rescnt -= len; --- 4834,4838 ---- if (sign && fill == ' ') *res++ = sign; ! memcpy(res, pbuf, len * sizeof(Py_UNICODE)); res += len; rescnt -= len;
-- Sjoerd Mullender <sjoerd.mullender@oratrix.com>