[Python-checkins] CVS: python/dist/src/Objects unicodeobject.c,2.31,2.32

M.-A. Lemburg python-dev@python.org
2000年6月30日 03:29:59 -0700


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;

AltStyle によって変換されたページ (->オリジナル) /