[Python-checkins] r61180 - in python/branches/release24-maint: Include/pymem.h Include/pyport.h Misc/NEWS Modules/_csv.c Modules/arraymodule.c Modules/audioop.c Modules/binascii.c Modules/cPickle.c Modules/cStringIO.c Modules/cjkcodecs/multibytecodec.c Modules/datetimemodule.c Modules/rgbimgmodule.c Modules/stropmodule.c Objects/bufferobject.c Objects/listobject.c Parser/node.c Python/bltinmodule.c
martin.v.loewis
python-checkins at python.org
Sun Mar 2 20:20:33 CET 2008
Author: martin.v.loewis
Date: Sun Mar 2 20:20:32 2008
New Revision: 61180
Modified:
python/branches/release24-maint/Include/pymem.h
python/branches/release24-maint/Include/pyport.h
python/branches/release24-maint/Misc/NEWS
python/branches/release24-maint/Modules/_csv.c
python/branches/release24-maint/Modules/arraymodule.c
python/branches/release24-maint/Modules/audioop.c
python/branches/release24-maint/Modules/binascii.c
python/branches/release24-maint/Modules/cPickle.c
python/branches/release24-maint/Modules/cStringIO.c
python/branches/release24-maint/Modules/cjkcodecs/multibytecodec.c
python/branches/release24-maint/Modules/datetimemodule.c
python/branches/release24-maint/Modules/rgbimgmodule.c
python/branches/release24-maint/Modules/stropmodule.c
python/branches/release24-maint/Objects/bufferobject.c
python/branches/release24-maint/Objects/listobject.c
python/branches/release24-maint/Parser/node.c
python/branches/release24-maint/Python/bltinmodule.c
Log:
Backport of r60793:
Added checks for integer overflows, contributed by Google. Some are
only available if asserts are left in the code, in cases where they
can't be triggered from Python code.
Modified: python/branches/release24-maint/Include/pymem.h
==============================================================================
--- python/branches/release24-maint/Include/pymem.h (original)
+++ python/branches/release24-maint/Include/pymem.h Sun Mar 2 20:20:32 2008
@@ -86,14 +86,18 @@
*/
#define PyMem_New(type, n) \
- ( (type *) PyMem_Malloc((n) * sizeof(type)) )
+ ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
+ ( (type *) PyMem_Malloc((n) * sizeof(type)) ) )
#define PyMem_NEW(type, n) \
- ( (type *) PyMem_MALLOC((n) * sizeof(type)) )
+ ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
+ ( (type *) PyMem_MALLOC((n) * sizeof(type)) ) )
#define PyMem_Resize(p, type, n) \
- ( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
+ ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
+ ( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) ) )
#define PyMem_RESIZE(p, type, n) \
- ( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
+ ( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
+ ( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) ) )
/* In order to avoid breaking old code mixing PyObject_{New, NEW} with
PyMem_{Del, DEL} and PyMem_{Free, FREE}, the PyMem "release memory"
Modified: python/branches/release24-maint/Include/pyport.h
==============================================================================
--- python/branches/release24-maint/Include/pyport.h (original)
+++ python/branches/release24-maint/Include/pyport.h Sun Mar 2 20:20:32 2008
@@ -616,6 +616,17 @@
#error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."
#endif
+/* Largest possible value of size_t.
+ SIZE_MAX is part of C99, so it might be defined on some
+ platforms. If it is not defined, (size_t)-1 is a portable
+ definition for C89, due to the way signed->unsigned
+ conversion is defined. */
+#ifdef SIZE_MAX
+#define PY_SIZE_MAX SIZE_MAX
+#else
+#define PY_SIZE_MAX ((size_t)-1)
+#endif
+
#ifdef __cplusplus
}
#endif
Modified: python/branches/release24-maint/Misc/NEWS
==============================================================================
--- python/branches/release24-maint/Misc/NEWS (original)
+++ python/branches/release24-maint/Misc/NEWS Sun Mar 2 20:20:32 2008
@@ -13,6 +13,10 @@
Core and builtins
-----------------
+- Added checks for integer overflows, contributed by Google. Some are
+ only available if asserts are left in the code, in cases where they
+ can't be triggered from Python code.
+
- patch #1630975: Fix crash when replacing sys.stdout in sitecustomize.py
Extension Modules
Modified: python/branches/release24-maint/Modules/_csv.c
==============================================================================
--- python/branches/release24-maint/Modules/_csv.c (original)
+++ python/branches/release24-maint/Modules/_csv.c Sun Mar 2 20:20:32 2008
@@ -470,6 +470,10 @@
self->field = PyMem_Malloc(self->field_size);
}
else {
+ if (self->field_size > INT_MAX / 2) {
+ PyErr_NoMemory();
+ return 0;
+ }
self->field_size *= 2;
self->field = PyMem_Realloc(self->field, self->field_size);
}
@@ -1003,6 +1007,12 @@
static int
join_check_rec_size(WriterObj *self, int rec_len)
{
+
+ if (rec_len < 0 || rec_len > INT_MAX - MEM_INCR) {
+ PyErr_NoMemory();
+ return 0;
+ }
+
if (rec_len > self->rec_size) {
if (self->rec_size == 0) {
self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;
Modified: python/branches/release24-maint/Modules/arraymodule.c
==============================================================================
--- python/branches/release24-maint/Modules/arraymodule.c (original)
+++ python/branches/release24-maint/Modules/arraymodule.c Sun Mar 2 20:20:32 2008
@@ -651,6 +651,9 @@
PyErr_BadArgument();
return NULL;
}
+ if (a->ob_size > INT_MAX - b->ob_size) {
+ return PyErr_NoMemory();
+ }
size = a->ob_size + b->ob_size;
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
if (np == NULL) {
@@ -673,6 +676,9 @@
int nbytes;
if (n < 0)
n = 0;
+ if ((a->ob_size != 0) && (n > INT_MAX / a->ob_size)) {
+ return PyErr_NoMemory();
+ }
size = a->ob_size * n;
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
if (np == NULL)
@@ -817,6 +823,11 @@
"can only extend with array of same kind");
return -1;
}
+ if ((self->ob_size > INT_MAX - b->ob_size) ||
+ ((self->ob_size + b->ob_size) > INT_MAX / self->ob_descr->itemsize)) {
+ PyErr_NoMemory();
+ return -1;
+ }
size = self->ob_size + b->ob_size;
PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
if (self->ob_item == NULL) {
@@ -858,6 +869,10 @@
if (n < 0)
n = 0;
items = self->ob_item;
+ if ((self->ob_descr->itemsize != 0) &&
+ (self->ob_size > INT_MAX / self->ob_descr->itemsize)) {
+ return PyErr_NoMemory();
+ }
size = self->ob_size * self->ob_descr->itemsize;
if (n == 0) {
PyMem_FREE(items);
@@ -866,6 +881,9 @@
self->allocated = 0;
}
else {
+ if (size > INT_MAX / n) {
+ return PyErr_NoMemory();
+ }
PyMem_Resize(items, char, n * size);
if (items == NULL)
return PyErr_NoMemory();
@@ -1278,6 +1296,9 @@
if ((*self->ob_descr->setitem)(self,
self->ob_size - n + i, v) != 0) {
self->ob_size -= n;
+ if (itemsize && (self->ob_size > INT_MAX / itemsize)) {
+ return PyErr_NoMemory();
+ }
PyMem_RESIZE(item, char,
self->ob_size * itemsize);
self->ob_item = item;
@@ -1337,6 +1358,10 @@
n = n / itemsize;
if (n > 0) {
char *item = self->ob_item;
+ if ((n > INT_MAX - self->ob_size) ||
+ ((self->ob_size + n) > INT_MAX / itemsize)) {
+ return PyErr_NoMemory();
+ }
PyMem_RESIZE(item, char, (self->ob_size + n) * itemsize);
if (item == NULL) {
PyErr_NoMemory();
@@ -1362,8 +1387,12 @@
static PyObject *
array_tostring(arrayobject *self, PyObject *unused)
{
- return PyString_FromStringAndSize(self->ob_item,
+ if (self->ob_size <= INT_MAX / self->ob_descr->itemsize) {
+ return PyString_FromStringAndSize(self->ob_item,
self->ob_size * self->ob_descr->itemsize);
+ } else {
+ return PyErr_NoMemory();
+ }
}
PyDoc_STRVAR(tostring_doc,
@@ -1391,6 +1420,9 @@
}
if (n > 0) {
Py_UNICODE *item = (Py_UNICODE *) self->ob_item;
+ if (self->ob_size > INT_MAX - n) {
+ return PyErr_NoMemory();
+ }
PyMem_RESIZE(item, Py_UNICODE, self->ob_size + n);
if (item == NULL) {
PyErr_NoMemory();
Modified: python/branches/release24-maint/Modules/audioop.c
==============================================================================
--- python/branches/release24-maint/Modules/audioop.c (original)
+++ python/branches/release24-maint/Modules/audioop.c Sun Mar 2 20:20:32 2008
@@ -674,7 +674,7 @@
audioop_tostereo(PyObject *self, PyObject *args)
{
signed char *cp, *ncp;
- int len, size, val1, val2, val = 0;
+ int len, new_len, size, val1, val2, val = 0;
double fac1, fac2, fval, maxval;
PyObject *rv;
int i;
@@ -690,7 +690,14 @@
return 0;
}
- rv = PyString_FromStringAndSize(NULL, len*2);
+ new_len = len*2;
+ if (new_len < 0) {
+ PyErr_SetString(PyExc_MemoryError,
+ "not enough memory for output buffer");
+ return 0;
+ }
+
+ rv = PyString_FromStringAndSize(NULL, new_len);
if ( rv == 0 )
return 0;
ncp = (signed char *)PyString_AsString(rv);
@@ -853,7 +860,7 @@
{
signed char *cp;
unsigned char *ncp;
- int len, size, size2, val = 0;
+ int len, new_len, size, size2, val = 0;
PyObject *rv;
int i, j;
@@ -867,7 +874,13 @@
return 0;
}
- rv = PyString_FromStringAndSize(NULL, (len/size)*size2);
+ new_len = (len/size)*size2;
+ if (new_len < 0) {
+ PyErr_SetString(PyExc_MemoryError,
+ "not enough memory for output buffer");
+ return 0;
+ }
+ rv = PyString_FromStringAndSize(NULL, new_len);
if ( rv == 0 )
return 0;
ncp = (unsigned char *)PyString_AsString(rv);
@@ -903,6 +916,7 @@
int chan, d, *prev_i, *cur_i, cur_o;
PyObject *state, *samps, *str, *rv = NULL;
int bytes_per_frame;
+ size_t alloc_size;
weightA = 1;
weightB = 0;
@@ -944,8 +958,14 @@
inrate /= d;
outrate /= d;
- prev_i = (int *) malloc(nchannels * sizeof(int));
- cur_i = (int *) malloc(nchannels * sizeof(int));
+ alloc_size = sizeof(int) * (unsigned)nchannels;
+ if (alloc_size < nchannels) {
+ PyErr_SetString(PyExc_MemoryError,
+ "not enough memory for output buffer");
+ return 0;
+ }
+ prev_i = (int *) malloc(alloc_size);
+ cur_i = (int *) malloc(alloc_size);
if (prev_i == NULL || cur_i == NULL) {
(void) PyErr_NoMemory();
goto exit;
@@ -1116,7 +1136,7 @@
unsigned char *cp;
unsigned char cval;
signed char *ncp;
- int len, size, val;
+ int len, new_len, size, val;
PyObject *rv;
int i;
@@ -1129,12 +1149,18 @@
return 0;
}
- rv = PyString_FromStringAndSize(NULL, len*size);
+ new_len = len*size;
+ if (new_len < 0) {
+ PyErr_SetString(PyExc_MemoryError,
+ "not enough memory for output buffer");
+ return 0;
+ }
+ rv = PyString_FromStringAndSize(NULL, new_len);
if ( rv == 0 )
return 0;
ncp = (signed char *)PyString_AsString(rv);
- for ( i=0; i < len*size; i += size ) {
+ for ( i=0; i < new_len; i += size ) {
cval = *cp++;
val = st_ulaw_to_linear(cval);
@@ -1259,7 +1285,7 @@
{
signed char *cp;
signed char *ncp;
- int len, size, valpred, step, delta, index, sign, vpdiff;
+ int len, new_len, size, valpred, step, delta, index, sign, vpdiff;
PyObject *rv, *str, *state;
int i, inputbuffer = 0, bufferstep;
@@ -1281,7 +1307,13 @@
} else if ( !PyArg_Parse(state, "(ii)", &valpred, &index) )
return 0;
- str = PyString_FromStringAndSize(NULL, len*size*2);
+ new_len = len*size*2;
+ if (new_len < 0) {
+ PyErr_SetString(PyExc_MemoryError,
+ "not enough memory for output buffer");
+ return 0;
+ }
+ str = PyString_FromStringAndSize(NULL, new_len);
if ( str == 0 )
return 0;
ncp = (signed char *)PyString_AsString(str);
@@ -1289,7 +1321,7 @@
step = stepsizeTable[index];
bufferstep = 0;
- for ( i=0; i < len*size*2; i += size ) {
+ for ( i=0; i < new_len; i += size ) {
/* Step 1 - get the delta value and compute next index */
if ( bufferstep ) {
delta = inputbuffer & 0xf;
Modified: python/branches/release24-maint/Modules/binascii.c
==============================================================================
--- python/branches/release24-maint/Modules/binascii.c (original)
+++ python/branches/release24-maint/Modules/binascii.c Sun Mar 2 20:20:32 2008
@@ -194,6 +194,8 @@
if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) )
return NULL;
+ assert(ascii_len >= 0);
+
/* First byte: binary data length (in bytes) */
bin_len = (*ascii_data++ - ' ') & 077;
ascii_len--;
@@ -347,6 +349,11 @@
if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) )
return NULL;
+ assert(ascii_len >= 0);
+
+ if (ascii_len > INT_MAX - 3)
+ return PyErr_NoMemory();
+
bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
/* Allocate the buffer */
@@ -436,6 +443,9 @@
if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) )
return NULL;
+
+ assert(bin_len >= 0);
+
if ( bin_len > BASE64_MAXBIN ) {
PyErr_SetString(Error, "Too much data for base64 line");
return NULL;
@@ -491,6 +501,11 @@
if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) )
return NULL;
+ assert(len >= 0);
+
+ if (len > INT_MAX - 2)
+ return PyErr_NoMemory();
+
/* Allocate a string that is too big (fixed later)
Add two to the initial length to prevent interning which
would preclude subsequent resizing. */
@@ -554,6 +569,11 @@
if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) )
return NULL;
+ assert(len >= 0);
+
+ if (len > INT_MAX / 2 - 2)
+ return PyErr_NoMemory();
+
/* Worst case: output is twice as big as input (fixed later) */
if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL )
return NULL;
@@ -603,6 +623,11 @@
if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) )
return NULL;
+ assert(len >= 0);
+
+ if (len > INT_MAX / 2 - 2)
+ return PyErr_NoMemory();
+
/* Allocate a buffer that is at least large enough */
if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL )
return NULL;
@@ -641,9 +666,13 @@
if ( !PyArg_ParseTuple(args, "s#:rledecode_hqx", &in_data, &in_len) )
return NULL;
+ assert(in_len >= 0);
+
/* Empty string is a special case */
if ( in_len == 0 )
return Py_BuildValue("s", "");
+ else if (in_len > INT_MAX / 2)
+ return PyErr_NoMemory();
/* Allocate a buffer of reasonable size. Resized when needed */
out_len = in_len*2;
@@ -669,6 +698,7 @@
#define OUTBYTE(b) \
do { \
if ( --out_len_left < 0 ) { \
+ if ( out_len > INT_MAX / 2) return PyErr_NoMemory(); \
_PyString_Resize(&rv, 2*out_len); \
if ( rv == NULL ) return NULL; \
out_data = (unsigned char *)PyString_AsString(rv) \
@@ -737,7 +767,7 @@
if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) )
return NULL;
- while(len--) {
+ while(len-- > 0) {
crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++];
}
@@ -881,7 +911,7 @@
/* only want the trailing 32 bits */
crc &= 0xFFFFFFFFUL;
#endif
- while (len--)
+ while (len-- > 0)
crc = crc_32_tab[(crc ^ *bin_data++) & 0xffUL] ^ (crc >> 8);
/* Note: (crc >> 8) MUST zero fill on left */
@@ -911,6 +941,10 @@
if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen))
return NULL;
+ assert(arglen >= 0);
+ if (arglen > INT_MAX / 2)
+ return PyErr_NoMemory();
+
retval = PyString_FromStringAndSize(NULL, arglen*2);
if (!retval)
return NULL;
@@ -968,6 +1002,8 @@
if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen))
return NULL;
+ assert(arglen >= 0);
+
/* XXX What should we do about strings with an odd length? Should
* we add an implicit leading zero, or a trailing zero? For now,
* raise an exception.
Modified: python/branches/release24-maint/Modules/cPickle.c
==============================================================================
--- python/branches/release24-maint/Modules/cPickle.c (original)
+++ python/branches/release24-maint/Modules/cPickle.c Sun Mar 2 20:20:32 2008
@@ -3419,6 +3419,14 @@
if (self->read_func(self, &s, 4) < 0) return -1;
l = calc_binint(s, 4);
+ if (l < 0) {
+ /* Corrupt or hostile pickle -- we never write one like
+ * this.
+ */
+ PyErr_SetString(UnpicklingError,
+ "BINSTRING pickle has negative byte count");
+ return -1;
+ }
if (self->read_func(self, &s, l) < 0)
return -1;
@@ -3486,6 +3494,14 @@
if (self->read_func(self, &s, 4) < 0) return -1;
l = calc_binint(s, 4);
+ if (l < 0) {
+ /* Corrupt or hostile pickle -- we never write one like
+ * this.
+ */
+ PyErr_SetString(UnpicklingError,
+ "BINUNICODE pickle has negative byte count");
+ return -1;
+ }
if (self->read_func(self, &s, l) < 0)
return -1;
Modified: python/branches/release24-maint/Modules/cStringIO.c
==============================================================================
--- python/branches/release24-maint/Modules/cStringIO.c (original)
+++ python/branches/release24-maint/Modules/cStringIO.c Sun Mar 2 20:20:32 2008
@@ -121,6 +121,7 @@
static PyObject *
IO_cgetval(PyObject *self) {
UNLESS (IO__opencheck(IOOOBJECT(self))) return NULL;
+ assert(IOOOBJECT(self)->pos >= 0);
return PyString_FromStringAndSize(((IOobject*)self)->buf,
((IOobject*)self)->pos);
}
@@ -139,6 +140,7 @@
}
else
s=self->string_size;
+ assert(self->pos >= 0);
return PyString_FromStringAndSize(self->buf, s);
}
@@ -158,6 +160,8 @@
int l;
UNLESS (IO__opencheck(IOOOBJECT(self))) return -1;
+ assert(IOOOBJECT(self)->pos >= 0);
+ assert(IOOOBJECT(self)->string_size >= 0);
l = ((IOobject*)self)->string_size - ((IOobject*)self)->pos;
if (n < 0 || n > l) {
n = l;
@@ -197,6 +201,11 @@
*output=((IOobject*)self)->buf + ((IOobject*)self)->pos;
l = n - ((IOobject*)self)->buf - ((IOobject*)self)->pos;
+
+ assert(IOOOBJECT(self)->pos <= INT_MAX - l);
+ assert(IOOOBJECT(self)->pos >= 0);
+ assert(IOOOBJECT(self)->string_size >= 0);
+
((IOobject*)self)->pos += l;
return l;
}
@@ -215,6 +224,7 @@
n -= m;
self->pos -= m;
}
+ assert(IOOOBJECT(self)->pos >= 0);
return PyString_FromStringAndSize(output, n);
}
@@ -277,6 +287,7 @@
UNLESS (IO__opencheck(self)) return NULL;
+ assert(self->pos >= 0);
return PyInt_FromLong(self->pos);
}
Modified: python/branches/release24-maint/Modules/cjkcodecs/multibytecodec.c
==============================================================================
--- python/branches/release24-maint/Modules/cjkcodecs/multibytecodec.c (original)
+++ python/branches/release24-maint/Modules/cjkcodecs/multibytecodec.c Sun Mar 2 20:20:32 2008
@@ -100,12 +100,16 @@
static int
expand_encodebuffer(MultibyteEncodeBuffer *buf, int esize)
{
- int orgpos, orgsize;
+ int orgpos, orgsize, incsize;
orgpos = (int)((char*)buf->outbuf - PyString_AS_STRING(buf->outobj));
orgsize = PyString_GET_SIZE(buf->outobj);
- if (_PyString_Resize(&buf->outobj, orgsize + (
- esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize)) == -1)
+ incsize = (esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize);
+
+ if (orgsize > INT_MAX - incsize)
+ return -1;
+
+ if (_PyString_Resize(&buf->outobj, orgsize + incsize) == -1)
return -1;
buf->outbuf = (unsigned char *)PyString_AS_STRING(buf->outobj) +orgpos;
@@ -416,6 +420,12 @@
buf.excobj = NULL;
buf.inbuf = buf.inbuf_top = *data;
buf.inbuf_end = buf.inbuf_top + datalen;
+
+ if (datalen > (INT_MAX - 16) / 2) {
+ PyErr_NoMemory();
+ goto errorexit;
+ }
+
buf.outobj = PyString_FromStringAndSize(NULL, datalen * 2 + 16);
if (buf.outobj == NULL)
goto errorexit;
@@ -725,6 +735,10 @@
PyObject *ctr;
char *ctrdata;
+ if (PyString_GET_SIZE(cres) > INT_MAX - self->pendingsize) {
+ PyErr_NoMemory();
+ goto errorexit;
+ }
rsize = PyString_GET_SIZE(cres) + self->pendingsize;
ctr = PyString_FromStringAndSize(NULL, rsize);
if (ctr == NULL)
Modified: python/branches/release24-maint/Modules/datetimemodule.c
==============================================================================
--- python/branches/release24-maint/Modules/datetimemodule.c (original)
+++ python/branches/release24-maint/Modules/datetimemodule.c Sun Mar 2 20:20:32 2008
@@ -1111,6 +1111,8 @@
char sign;
int none;
+ assert(buflen >= 1);
+
offset = call_utcoffset(tzinfo, tzinfoarg, &none);
if (offset == -1 && PyErr_Occurred())
return -1;
@@ -1188,6 +1190,11 @@
* a new format. Since computing the replacements for those codes
* is expensive, don't unless they're actually used.
*/
+ if (PyString_Size(format) > INT_MAX - 1) {
+ PyErr_NoMemory();
+ goto Done;
+ }
+
totalnew = PyString_Size(format) + 1; /* realistic if no %z/%Z */
newfmt = PyString_FromStringAndSize(NULL, totalnew);
if (newfmt == NULL) goto Done;
Modified: python/branches/release24-maint/Modules/rgbimgmodule.c
==============================================================================
--- python/branches/release24-maint/Modules/rgbimgmodule.c (original)
+++ python/branches/release24-maint/Modules/rgbimgmodule.c Sun Mar 2 20:20:32 2008
@@ -269,7 +269,7 @@
Py_Int32 *starttab = NULL, *lengthtab = NULL;
FILE *inf = NULL;
IMAGE image;
- int y, z, tablen;
+ int y, z, tablen, new_size;
int xsize, ysize, zsize;
int bpp, rle, cur, badorder;
int rlebuflen;
@@ -301,9 +301,15 @@
zsize = image.zsize;
if (rle) {
tablen = ysize * zsize * sizeof(Py_Int32);
+ rlebuflen = (int) (1.05 * xsize +10);
+ if ((tablen / sizeof(Py_Int32)) != (ysize * zsize) ||
+ rlebuflen < 0) {
+ PyErr_NoMemory();
+ goto finally;
+ }
+
starttab = (Py_Int32 *)malloc(tablen);
lengthtab = (Py_Int32 *)malloc(tablen);
- rlebuflen = (int) (1.05 * xsize +10);
rledat = (unsigned char *)malloc(rlebuflen);
if (!starttab || !lengthtab || !rledat) {
PyErr_NoMemory();
@@ -331,8 +337,14 @@
fseek(inf, 512 + 2 * tablen, SEEK_SET);
cur = 512 + 2 * tablen;
+ new_size = xsize * ysize + TAGLEN;
+ if (new_size < 0 || (new_size * sizeof(Py_Int32)) < 0) {
+ PyErr_NoMemory();
+ goto finally;
+ }
+
rv = PyString_FromStringAndSize((char *)NULL,
- (xsize * ysize + TAGLEN) * sizeof(Py_Int32));
+ new_size * sizeof(Py_Int32));
if (rv == NULL)
goto finally;
@@ -400,8 +412,14 @@
copybw((Py_Int32 *) base, xsize * ysize);
}
else {
+ new_size = xsize * ysize + TAGLEN;
+ if (new_size < 0 || (new_size * sizeof(Py_Int32)) < 0) {
+ PyErr_NoMemory();
+ goto finally;
+ }
+
rv = PyString_FromStringAndSize((char *) 0,
- (xsize*ysize+TAGLEN)*sizeof(Py_Int32));
+ new_size*sizeof(Py_Int32));
if (rv == NULL)
goto finally;
@@ -590,10 +608,16 @@
return NULL;
}
tablen = ysize * zsize * sizeof(Py_Int32);
+ rlebuflen = (int) (1.05 * xsize + 10);
+
+ if ((tablen / sizeof(Py_Int32)) != (ysize * zsize) ||
+ rlebuflen < 0 || (xsize * sizeof(Py_Int32)) < 0) {
+ PyErr_NoMemory();
+ goto finally;
+ }
starttab = (Py_Int32 *)malloc(tablen);
lengthtab = (Py_Int32 *)malloc(tablen);
- rlebuflen = (int) (1.05 * xsize + 10);
rlebuf = (unsigned char *)malloc(rlebuflen);
lumbuf = (unsigned char *)malloc(xsize * sizeof(Py_Int32));
if (!starttab || !lengthtab || !rlebuf || !lumbuf) {
Modified: python/branches/release24-maint/Modules/stropmodule.c
==============================================================================
--- python/branches/release24-maint/Modules/stropmodule.c (original)
+++ python/branches/release24-maint/Modules/stropmodule.c Sun Mar 2 20:20:32 2008
@@ -576,7 +576,7 @@
char* e;
char* p;
char* q;
- int i, j;
+ int i, j, old_j;
PyObject* out;
char* string;
int stringlen;
@@ -593,12 +593,18 @@
}
/* First pass: determine size of output string */
- i = j = 0; /* j: current column; i: total of previous lines */
+ i = j = old_j = 0; /* j: current column; i: total of previous lines */
e = string + stringlen;
for (p = string; p < e; p++) {
- if (*p == '\t')
+ if (*p == '\t') {
j += tabsize - (j%tabsize);
- else {
+ if (old_j > j) {
+ PyErr_SetString(PyExc_OverflowError,
+ "new string is too long");
+ return NULL;
+ }
+ old_j = j;
+ } else {
j++;
if (*p == '\n') {
i += j;
@@ -607,6 +613,11 @@
}
}
+ if ((i + j) < 0) {
+ PyErr_SetString(PyExc_OverflowError, "new string is too long");
+ return NULL;
+ }
+
/* Second pass: create output string and fill it */
out = PyString_FromStringAndSize(NULL, i+j);
if (out == NULL)
Modified: python/branches/release24-maint/Objects/bufferobject.c
==============================================================================
--- python/branches/release24-maint/Objects/bufferobject.c (original)
+++ python/branches/release24-maint/Objects/bufferobject.c Sun Mar 2 20:20:32 2008
@@ -167,6 +167,10 @@
"size must be zero or positive");
return NULL;
}
+ if (sizeof(*b) > INT_MAX - size) {
+ /* unlikely */
+ return PyErr_NoMemory();
+ }
/* Inline PyObject_New */
o = PyObject_MALLOC(sizeof(*b) + size);
if ( o == NULL )
@@ -355,6 +359,8 @@
if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
return NULL;
+ assert(count <= PY_SIZE_MAX - size);
+
ob = PyString_FromStringAndSize(NULL, size + count);
p = PyString_AS_STRING(ob);
memcpy(p, ptr1, size);
Modified: python/branches/release24-maint/Objects/listobject.c
==============================================================================
--- python/branches/release24-maint/Objects/listobject.c (original)
+++ python/branches/release24-maint/Objects/listobject.c Sun Mar 2 20:20:32 2008
@@ -45,7 +45,16 @@
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
- new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
+ new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
+
+ /* check for integer overflow */
+ if (new_allocated > PY_SIZE_MAX - newsize) {
+ PyErr_NoMemory();
+ return -1;
+ } else {
+ new_allocated += newsize;
+ }
+
if (newsize == 0)
new_allocated = 0;
items = self->ob_item;
@@ -92,8 +101,9 @@
return NULL;
}
nbytes = size * sizeof(PyObject *);
- /* Check for overflow */
- if (nbytes / sizeof(PyObject *) != (size_t)size)
+ /* Check for overflow without an actual overflow,
+ * which can cause compiler to optimise out */
+ if (size > PY_SIZE_MAX / sizeof(PyObject *))
return PyErr_NoMemory();
if (num_free_lists) {
num_free_lists--;
@@ -1372,6 +1382,10 @@
* we don't care what's in the block.
*/
merge_freemem(ms);
+ if (need > INT_MAX / sizeof(PyObject*)) {
+ PyErr_NoMemory();
+ return -1;
+ }
ms->a = (PyObject **)PyMem_Malloc(need * sizeof(PyObject*));
if (ms->a) {
ms->alloced = need;
@@ -2550,6 +2564,8 @@
step = -step;
}
+ assert(slicelength <= PY_SIZE_MAX / sizeof(PyObject*));
+
garbage = (PyObject**)
PyMem_MALLOC(slicelength*sizeof(PyObject*));
if (!garbage) {
Modified: python/branches/release24-maint/Parser/node.c
==============================================================================
--- python/branches/release24-maint/Parser/node.c (original)
+++ python/branches/release24-maint/Parser/node.c Sun Mar 2 20:20:32 2008
@@ -91,6 +91,9 @@
if (current_capacity < 0 || required_capacity < 0)
return E_OVERFLOW;
if (current_capacity < required_capacity) {
+ if (required_capacity > PY_SIZE_MAX / sizeof(node)) {
+ return E_NOMEM;
+ }
n = n1->n_child;
n = (node *) PyObject_REALLOC(n,
required_capacity * sizeof(node));
Modified: python/branches/release24-maint/Python/bltinmodule.c
==============================================================================
--- python/branches/release24-maint/Python/bltinmodule.c (original)
+++ python/branches/release24-maint/Python/bltinmodule.c Sun Mar 2 20:20:32 2008
@@ -2376,11 +2376,43 @@
PyString_AS_STRING(item)[0];
} else {
/* do we need more space? */
- int need = j + reslen + len-i-1;
+ int need = j;
+
+ /* calculate space requirements while checking for overflow */
+ if (need > INT_MAX - reslen) {
+ Py_DECREF(item);
+ goto Fail_1;
+ }
+
+ need += reslen;
+
+ if (need > INT_MAX - len) {
+ Py_DECREF(item);
+ goto Fail_1;
+ }
+
+ need += len;
+
+ if (need <= i) {
+ Py_DECREF(item);
+ goto Fail_1;
+ }
+
+ need = need - i - 1;
+
+ assert(need >= 0);
+ assert(outlen >= 0);
+
if (need > outlen) {
/* overallocate, to avoid reallocations */
- if (need<2*outlen)
+ if (outlen > INT_MAX / 2) {
+ Py_DECREF(item);
+ return NULL;
+ }
+
+ if (need<2*outlen) {
need = 2*outlen;
+ }
if (_PyString_Resize(&result, need)) {
Py_DECREF(item);
return NULL;
@@ -2472,11 +2504,31 @@
else {
/* do we need more space? */
int need = j + reslen + len - i - 1;
+
+ /* check that didnt overflow */
+ if ((j > INT_MAX - reslen) ||
+ ((j + reslen) > INT_MAX - len) ||
+ ((j + reslen + len) < i) ||
+ ((j + reslen + len - i) <= 0)) {
+ Py_DECREF(item);
+ return NULL;
+ }
+
+ assert(need >= 0);
+ assert(outlen >= 0);
+
if (need > outlen) {
/* overallocate,
to avoid reallocations */
- if (need < 2 * outlen)
- need = 2 * outlen;
+ if (need < 2 * outlen) {
+ if (outlen > INT_MAX / 2) {
+ Py_DECREF(item);
+ return NULL;
+ } else {
+ need = 2 * outlen;
+ }
+ }
+
if (PyUnicode_Resize(
&result, need) < 0) {
Py_DECREF(item);
More information about the Python-checkins
mailing list