]> granicus.if.org Git - python/commitdiff
Added checks for integer overflows, contributed by Google. Some are
authorMartin v. Löwis <martin@v.loewis.de>
Thu, 14 Feb 2008 11:26:18 +0000 (11:26 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Thu, 14 Feb 2008 11:26:18 +0000 (11:26 +0000)
only available if asserts are left in the code, in cases where they
can't be triggered from Python code.

25 files changed:
Include/pymem.h
Include/pyport.h
Lib/test/test_array.py
Lib/test/test_struct.py
Misc/NEWS
Modules/_csv.c
Modules/_struct.c
Modules/arraymodule.c
Modules/audioop.c
Modules/binascii.c
Modules/cPickle.c
Modules/cStringIO.c
Modules/cjkcodecs/multibytecodec.c
Modules/datetimemodule.c
Modules/md5.c
Modules/rgbimgmodule.c
Modules/stropmodule.c
Objects/bufferobject.c
Objects/listobject.c
Objects/obmalloc.c
Parser/node.c
Python/asdl.c
Python/ast.c
Python/bltinmodule.c
Python/compile.c

index 671f967c8913b6ccbc90351abe63daf431c42ad8..0ab946301601d9b821f2d8c3c81d18ab3c15a789 100644 (file)
@@ -83,14 +83,18 @@ PyAPI_FUNC(void) PyMem_Free(void *);
  */
 
 #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)) ) )
 
 /* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used
  * anymore.  They're just confusing aliases for PyMem_{Free,FREE} now.
index d579be296b502aadf763cada140434a5b5ef0f9d..9ddcbf34e49064bc6b03f0f61bec5999222e8ca5 100644 (file)
@@ -117,6 +117,17 @@ typedef Py_intptr_t        Py_ssize_t;
 #   error "Python needs a typedef for Py_ssize_t in pyport.h."
 #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
+
 /* Largest positive value of type Py_ssize_t. */
 #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))
 /* Smallest negative value of type Py_ssize_t. */
index 597f3b24219556185f2a11bc2544e1cd30695d5b..a665bacc25f2de772a5af3c615727590fc71d212 100755 (executable)
@@ -975,6 +975,23 @@ tests.append(FloatTest)
 class DoubleTest(FPTest):
     typecode = 'd'
     minitemsize = 8
+
+    def test_alloc_overflow(self):
+        a = array.array('d', [-1]*65536)
+        try:
+            a *= 65536
+        except MemoryError:
+            pass
+        else:
+            self.fail("a *= 2**16 didn't raise MemoryError")
+        b = array.array('d', [ 2.71828183, 3.14159265, -1])
+        try:
+            b * 1431655766
+        except MemoryError:
+            pass
+        else:
+            self.fail("a * 1431655766 didn't raise MemoryError")
+
 tests.append(DoubleTest)
 
 def test_main(verbose=None):
index 7ecb6ac9a04dd9dde5642cef41d084c4863f41fb..71e35adc0f2b86c7b955538c47258cba0cfa5199 100644 (file)
@@ -618,8 +618,12 @@ def test_unpack_with_buffer():
     value, = struct.unpack('>I', data)
     vereq(value, 0x12345678)
 
+def test_crasher():
+    assertRaises(MemoryError, struct.pack, "357913941c", "a")
+
 # Test methods to pack and unpack from buffers rather than strings.
 test_unpack_from()
 test_pack_into()
 test_pack_into_fn()
 test_unpack_with_buffer()
+test_crasher()
index 6ea4eeaec33fbc53099027c9f7417aa1e40a45c8..cb8d4c525247d995cda43b18048a0304e0c749c9 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 2.5.2c1?
 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.
+
 - Issue #2045: Fix an infinite recursion triggered when printing a subclass of
   collections.defaultdict, if its default_factory is set to a bound method.
 
index 5e036355977a7615c2cfde7ca0c52c6a215b8690..2cd91998e1384a80da6c315dd90a605682b5fd6c 100644 (file)
@@ -560,6 +560,10 @@ parse_grow_buff(ReaderObj *self)
                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);
        }
@@ -1055,6 +1059,12 @@ join_append_data(WriterObj *self, char *field, int quote_empty,
 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;
index 53c64848b18eee27d2f979804137c4e8abf2bc79..41183fa26b5bcb0db970c223fb981b10500f78a2 100644 (file)
@@ -1336,6 +1336,12 @@ prepare_s(PyStructObject *self)
                }
        }
 
+       /* check for overflow */
+       if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) {
+               PyErr_NoMemory();
+               return -1;
+       }
+
        self->s_size = size;
        self->s_len = len;
        codes = PyMem_MALLOC((len + 1) * sizeof(formatcode));
index 3ba5cf88e16c8d9f244664d9e4191221f608fb49..da6e88f1295973c2f1992ba5511a54343b4adb3e 100644 (file)
@@ -652,6 +652,9 @@ array_concat(arrayobject *a, PyObject *bb)
                PyErr_BadArgument();
                return NULL;
        }
+       if (a->ob_size > PY_SSIZE_T_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) {
@@ -674,6 +677,9 @@ array_repeat(arrayobject *a, Py_ssize_t n)
        Py_ssize_t nbytes;
        if (n < 0)
                n = 0;
+       if ((a->ob_size != 0) && (n > PY_SSIZE_T_MAX / a->ob_size)) {
+               return PyErr_NoMemory();
+       }
        size = a->ob_size * n;
        np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
        if (np == NULL)
@@ -818,6 +824,11 @@ array_do_extend(arrayobject *self, PyObject *bb)
                             "can only extend with array of same kind");
                return -1;
        }
+       if ((self->ob_size > PY_SSIZE_T_MAX - b->ob_size) ||
+               ((self->ob_size + b->ob_size) > PY_SSIZE_T_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) {
@@ -859,6 +870,10 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
                if (n < 0)
                        n = 0;
                items = self->ob_item;
+               if ((self->ob_descr->itemsize != 0) && 
+                       (self->ob_size > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
+                       return PyErr_NoMemory();
+               }
                size = self->ob_size * self->ob_descr->itemsize;
                if (n == 0) {
                        PyMem_FREE(items);
@@ -867,6 +882,9 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
                        self->allocated = 0;
                }
                else {
+                       if (size > PY_SSIZE_T_MAX / n) {
+                               return PyErr_NoMemory();
+                       }
                        PyMem_Resize(items, char, n * size);
                        if (items == NULL)
                                return PyErr_NoMemory();
@@ -1148,6 +1166,10 @@ array_reduce(arrayobject *array)
                Py_INCREF(dict);
        }
        if (array->ob_size > 0) {
+               if (array->ob_descr->itemsize 
+                               > PY_SSIZE_T_MAX / array->ob_size) {
+                       return PyErr_NoMemory();
+               }
                result = Py_BuildValue("O(cs#)O", 
                        array->ob_type, 
                        array->ob_descr->typecode,
@@ -1310,6 +1332,9 @@ array_fromlist(arrayobject *self, PyObject *list)
                        if ((*self->ob_descr->setitem)(self,
                                        self->ob_size - n + i, v) != 0) {
                                self->ob_size -= n;
+                               if (itemsize && (self->ob_size > PY_SSIZE_T_MAX / itemsize)) {
+                                       return PyErr_NoMemory();
+                               }
                                PyMem_RESIZE(item, char,
                                                  self->ob_size * itemsize);
                                self->ob_item = item;
@@ -1369,6 +1394,10 @@ array_fromstring(arrayobject *self, PyObject *args)
        n = n / itemsize;
        if (n > 0) {
                char *item = self->ob_item;
+               if ((n > PY_SSIZE_T_MAX - self->ob_size) ||
+                       ((self->ob_size + n) > PY_SSIZE_T_MAX / itemsize)) {
+                               return PyErr_NoMemory();
+               }
                PyMem_RESIZE(item, char, (self->ob_size + n) * itemsize);
                if (item == NULL) {
                        PyErr_NoMemory();
@@ -1394,8 +1423,12 @@ values,as if it had been read from a file using the fromfile() method).");
 static PyObject *
 array_tostring(arrayobject *self, PyObject *unused)
 {
-       return PyString_FromStringAndSize(self->ob_item,
+       if (self->ob_size <= PY_SSIZE_T_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,
@@ -1423,6 +1456,9 @@ array_fromunicode(arrayobject *self, PyObject *args)
        }
        if (n > 0) {
                Py_UNICODE *item = (Py_UNICODE *) self->ob_item;
+               if (self->ob_size > PY_SSIZE_T_MAX - n) {
+                       return PyErr_NoMemory();
+               }
                PyMem_RESIZE(item, Py_UNICODE, self->ob_size + n);
                if (item == NULL) {
                        PyErr_NoMemory();
index 8f5d30c80585d90ceeb633bbb0117c7f86f5fcc4..04355c17b00430e884639f508f5a624c84e83ce9 100644 (file)
@@ -824,7 +824,7 @@ static PyObject *
 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;
@@ -841,7 +841,14 @@ audioop_tostereo(PyObject *self, PyObject *args)
                 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);
@@ -1004,7 +1011,7 @@ audioop_lin2lin(PyObject *self, PyObject *args)
 {
         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;
 
@@ -1018,7 +1025,13 @@ audioop_lin2lin(PyObject *self, PyObject *args)
                 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);
@@ -1054,6 +1067,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
         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;
@@ -1096,8 +1110,14 @@ audioop_ratecv(PyObject *self, PyObject *args)
         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;
@@ -1271,7 +1291,7 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
         unsigned char *cp;
         unsigned char cval;
         signed char *ncp;
-        int len, size, val;
+        int len, new_len, size, val;
         PyObject *rv;
         int i;
 
@@ -1284,12 +1304,18 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
                 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_ulaw2linear16(cval);
         
@@ -1339,7 +1365,7 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
         unsigned char *cp;
         unsigned char cval;
         signed char *ncp;
-        int len, size, val;
+        int len, new_len, size, val;
         PyObject *rv;
         int i;
 
@@ -1352,12 +1378,18 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
                 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_alaw2linear16(cval);
         
@@ -1482,7 +1514,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
 {
         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;
 
@@ -1504,7 +1536,13 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
         } else if ( !PyArg_ParseTuple(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);
@@ -1512,7 +1550,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
         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;
index 00f950d19da426bc4d282004f3be270b0e1ee248..fa221466681369f3409f680ed30a813f37d443a3 100644 (file)
@@ -138,7 +138,7 @@ static char table_a2b_base64[] = {
 #define BASE64_PAD '='
 
 /* Max binary chunk size; limited only by available memory */
-#define BASE64_MAXBIN (INT_MAX/2 - sizeof(PyStringObject) - 3)
+#define BASE64_MAXBIN (PY_SSIZE_T_MAX/2 - sizeof(PyStringObject) - 3)
 
 static unsigned char table_b2a_base64[] =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -195,6 +195,8 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
        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--;
@@ -348,6 +350,11 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
        if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) )
                return NULL;
 
+       assert(ascii_len >= 0);
+
+       if (ascii_len > PY_SSIZE_T_MAX - 3)
+               return PyErr_NoMemory();
+
        bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
 
        /* Allocate the buffer */
@@ -437,6 +444,9 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
 
        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;
@@ -492,6 +502,11 @@ binascii_a2b_hqx(PyObject *self, PyObject *args)
        if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) )
                return NULL;
 
+       assert(len >= 0);
+
+       if (len > PY_SSIZE_T_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.  */
@@ -555,6 +570,11 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
        if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) )
                return NULL;
 
+       assert(len >= 0);
+
+       if (len > PY_SSIZE_T_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;
@@ -604,6 +624,11 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
        if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) )
                return NULL;
 
+       assert(len >= 0);
+
+       if (len > PY_SSIZE_T_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;
@@ -642,9 +667,13 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
        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 PyString_FromString("");
+    else if (in_len > PY_SSIZE_T_MAX / 2)
+        return PyErr_NoMemory();
 
        /* Allocate a buffer of reasonable size. Resized when needed */
        out_len = in_len*2;
@@ -670,6 +699,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
 #define OUTBYTE(b) \
        do { \
                 if ( --out_len_left < 0 ) { \
+                         if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \
                          _PyString_Resize(&rv, 2*out_len); \
                          if ( rv == NULL ) return NULL; \
                          out_data = (unsigned char *)PyString_AsString(rv) \
@@ -738,7 +768,7 @@ binascii_crc_hqx(PyObject *self, PyObject *args)
        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++];
        }
 
@@ -882,7 +912,7 @@ binascii_crc32(PyObject *self, PyObject *args)
        /* 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 */
 
@@ -912,6 +942,10 @@ binascii_hexlify(PyObject *self, PyObject *args)
        if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen))
                return NULL;
 
+       assert(arglen >= 0);
+       if (arglen > PY_SSIZE_T_MAX / 2)
+               return PyErr_NoMemory();
+
        retval = PyString_FromStringAndSize(NULL, arglen*2);
        if (!retval)
                return NULL;
@@ -969,6 +1003,8 @@ binascii_unhexlify(PyObject *self, PyObject *args)
        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.
index b552a4033ac090e3886deb873f7a4c5a2c445631..537276c82cbad90b0a595c37784589a5f498bcf6 100644 (file)
@@ -3432,6 +3432,14 @@ load_binstring(Unpicklerobject *self)
        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;
@@ -3499,6 +3507,14 @@ load_binunicode(Unpicklerobject *self)
        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;
index a6fad9cbf37908e59cdb972325d1e9aa7912b8b2..8fbb4f9af644c6b43a2cd53039cb82214f4622ed 100644 (file)
@@ -119,6 +119,7 @@ PyDoc_STRVAR(IO_getval__doc__,
 static PyObject *
 IO_cgetval(PyObject *self) {
         if (!IO__opencheck(IOOOBJECT(self))) return NULL;
+        assert(IOOOBJECT(self)->pos >= 0);
         return PyString_FromStringAndSize(((IOobject*)self)->buf,
                                           ((IOobject*)self)->pos);
 }
@@ -137,6 +138,7 @@ IO_getval(IOobject *self, PyObject *args) {
         }
         else
                   s=self->string_size;
+        assert(self->pos >= 0);
         return PyString_FromStringAndSize(self->buf, s);
 }
 
@@ -157,6 +159,8 @@ IO_cread(PyObject *self, char **output, Py_ssize_t  n) {
         Py_ssize_t l;
 
         if (!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;
@@ -192,12 +196,17 @@ IO_creadline(PyObject *self, char **output) {
         for (n = ((IOobject*)self)->buf + ((IOobject*)self)->pos,
                s = ((IOobject*)self)->buf + ((IOobject*)self)->string_size; 
              n < s && *n != '\n'; n++);
+
         if (n < s) n++;
 
         *output=((IOobject*)self)->buf + ((IOobject*)self)->pos;
         l = n - ((IOobject*)self)->buf - ((IOobject*)self)->pos;
-       assert(((IOobject*)self)->pos + l < INT_MAX);
-        ((IOobject*)self)->pos += (int)l;
+
+        assert(IOOOBJECT(self)->pos <= PY_SSIZE_T_MAX - l);
+        assert(IOOOBJECT(self)->pos >= 0);
+        assert(IOOOBJECT(self)->string_size >= 0);
+
+        ((IOobject*)self)->pos += l;
         return (int)l;
 }
 
@@ -215,6 +224,7 @@ IO_readline(IOobject *self, PyObject *args) {
                 n -= m;
                 self->pos -= m;
         }
+        assert(IOOOBJECT(self)->pos >= 0);
         return PyString_FromStringAndSize(output, n);
 }
 
@@ -277,6 +287,7 @@ IO_tell(IOobject *self, PyObject *unused) {
 
         if (!IO__opencheck(self)) return NULL;
 
+        assert(self->pos >= 0);
         return PyInt_FromSsize_t(self->pos);
 }
 
index 9fb9570225edb36c02d8faa149fa30803b03e828..8a2b660783fc3adc840e9146f6200732c94baf61 100644 (file)
@@ -163,13 +163,17 @@ static PyGetSetDef codecctx_getsets[] = {
 static int
 expand_encodebuffer(MultibyteEncodeBuffer *buf, Py_ssize_t esize)
 {
-       Py_ssize_t orgpos, orgsize;
+       Py_ssize_t orgpos, orgsize, incsize;
 
        orgpos = (Py_ssize_t)((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 > PY_SSIZE_T_MAX - incsize)
+               return -1;
+
+       if (_PyString_Resize(&buf->outobj, orgsize + incsize) == -1)
                return -1;
 
        buf->outbuf = (unsigned char *)PyString_AS_STRING(buf->outobj) +orgpos;
@@ -473,6 +477,12 @@ multibytecodec_encode(MultibyteCodec *codec,
        buf.excobj = NULL;
        buf.inbuf = buf.inbuf_top = *data;
        buf.inbuf_end = buf.inbuf_top + datalen;
+
+       if (datalen > (PY_SSIZE_T_MAX - 16) / 2) {
+               PyErr_NoMemory();
+               goto errorexit;
+       }
+
        buf.outobj = PyString_FromStringAndSize(NULL, datalen * 2 + 16);
        if (buf.outobj == NULL)
                goto errorexit;
@@ -736,6 +746,11 @@ encoder_encode_stateful(MultibyteStatefulEncoderContext *ctx,
        origpending = ctx->pendingsize;
 
        if (origpending > 0) {
+               if (datalen > PY_SSIZE_T_MAX - ctx->pendingsize) {
+                       PyErr_NoMemory();
+                       /* inbuf_tmp == NULL */
+                       goto errorexit;
+               }
                inbuf_tmp = PyMem_New(Py_UNICODE, datalen + ctx->pendingsize);
                if (inbuf_tmp == NULL)
                        goto errorexit;
@@ -798,9 +813,10 @@ decoder_append_pending(MultibyteStatefulDecoderContext *ctx,
        Py_ssize_t npendings;
 
        npendings = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
-       if (npendings + ctx->pendingsize > MAXDECPENDING) {
-               PyErr_SetString(PyExc_UnicodeError, "pending buffer overflow");
-               return -1;
+       if (npendings + ctx->pendingsize > MAXDECPENDING ||
+               npendings > PY_SSIZE_T_MAX - ctx->pendingsize) {
+                       PyErr_SetString(PyExc_UnicodeError, "pending buffer overflow");
+                       return -1;
        }
        memcpy(ctx->pending + ctx->pendingsize, buf->inbuf, npendings);
        ctx->pendingsize += npendings;
@@ -1003,7 +1019,7 @@ mbidecoder_decode(MultibyteIncrementalDecoderObject *self,
                  PyObject *args, PyObject *kwargs)
 {
        MultibyteDecodeBuffer buf;
-       char *data, *wdata;
+       char *data, *wdata = NULL;
        Py_ssize_t wsize, finalsize = 0, size, origpending;
        int final = 0;
 
@@ -1019,6 +1035,10 @@ mbidecoder_decode(MultibyteIncrementalDecoderObject *self,
                wdata = data;
        }
        else {
+               if (size > PY_SSIZE_T_MAX - self->pendingsize) {
+                       PyErr_NoMemory();
+                       goto errorexit;
+               }
                wsize = size + self->pendingsize;
                wdata = PyMem_Malloc(wsize);
                if (wdata == NULL)
@@ -1238,6 +1258,10 @@ mbstreamreader_iread(MultibyteStreamReaderObject *self,
                        PyObject *ctr;
                        char *ctrdata;
 
+                       if (PyString_GET_SIZE(cres) > PY_SSIZE_T_MAX - self->pendingsize) {
+                               PyErr_NoMemory();
+                               goto errorexit;
+            }
                        rsize = PyString_GET_SIZE(cres) + self->pendingsize;
                        ctr = PyString_FromStringAndSize(NULL, rsize);
                        if (ctr == NULL)
index a67c35de4e91fd6ce3b81a44c22dadae9f4bf252..34112c01d41a654591e9a48786fe1cf08c14fe48 100644 (file)
@@ -1113,6 +1113,8 @@ format_utcoffset(char *buf, size_t buflen, const char *sep,
        char sign;
        int none;
 
+       assert(buflen >= 1);
+
        offset = call_utcoffset(tzinfo, tzinfoarg, &none);
        if (offset == -1 && PyErr_Occurred())
                return -1;
@@ -1190,6 +1192,11 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
         * 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;
index c35d96c5ef54848f670132e6660c0f9b58e291a2..0e1058f5cce01e73096143755cb12465f221dd2c 100644 (file)
@@ -53,6 +53,7 @@
 
 #include "md5.h"
 #include <string.h>
+#include <limits.h>
 
 #undef BYTE_ORDER      /* 1 = big-endian, -1 = little-endian, 0 = unknown */
 #ifdef ARCH_IS_BIG_ENDIAN
@@ -330,6 +331,18 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
     if (nbytes <= 0)
        return;
 
+    /* this special case is handled recursively */
+    if (nbytes > INT_MAX - offset) {
+        int overlap;
+
+        /* handle the append in two steps to prevent overflow */
+        overlap = 64 - offset;
+
+        md5_append(pms, data, overlap);
+        md5_append(pms, data + overlap, nbytes - overlap); 
+        return;
+    }
+
     /* Update the message length. */
     pms->count[1] += nbytes >> 29;
     pms->count[0] += nbits;
index 0f9ee71f241f7a16bb77405603f81a9a53f54751..3eb2f5534f3d2aeae0d33b14cf76e0be74f946f4 100644 (file)
@@ -269,7 +269,7 @@ longimagedata(PyObject *self, PyObject *args)
        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 @@ longimagedata(PyObject *self, PyObject *args)
        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 @@ longimagedata(PyObject *self, PyObject *args)
 
                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 @@ longimagedata(PyObject *self, PyObject *args)
                        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;
 
@@ -591,10 +609,16 @@ longstoimage(PyObject *self, PyObject *args)
                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) {
index 8b00fed69a8434da5f5495a45bbadae6f8554b68..bc609590d4c0e468ba1035b407075ae00504776e 100644 (file)
@@ -578,7 +578,7 @@ strop_expandtabs(PyObject *self, PyObject *args)
        char* e;
        char* p;
        char* q;
-       Py_ssize_t i, j;
+       Py_ssize_t i, j, old_j;
        PyObject* out;
        char* string;
        Py_ssize_t stringlen;
@@ -595,12 +595,18 @@ strop_expandtabs(PyObject *self, PyObject *args)
        }
 
        /* 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;
@@ -609,6 +615,11 @@ strop_expandtabs(PyObject *self, PyObject *args)
                }
        }
 
+       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)
index 86515ab4f8d8719a1572b4b67b230a4d8913c993..88c0e417fee17af9fb105631eb1937e1c9516cf2 100644 (file)
@@ -207,7 +207,10 @@ PyBuffer_New(Py_ssize_t size)
                                "size must be zero or positive");
                return NULL;
        }
-       /* XXX: check for overflow in multiply */
+       if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
+               /* unlikely */
+               return PyErr_NoMemory();
+       }
        /* Inline PyObject_New */
        o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
        if ( o == NULL )
@@ -397,6 +400,8 @@ buffer_concat(PyBufferObject *self, PyObject *other)
        if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
                return NULL;
 
+       assert(count <= PY_SIZE_MAX - size);
+
        ob = PyString_FromStringAndSize(NULL, size + count);
        if ( ob == NULL )
                return NULL;
index c1cacaf5eead7bc0af6ca7382812b642b2c4da45..9ec7b29eb1d44dd88ba1e110c0e91d69296bc56f 100644 (file)
@@ -45,7 +45,16 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
         * 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 @@ PyList_New(Py_ssize_t size)
                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 @@ merge_getmem(MergeState *ms, Py_ssize_t need)
         * we don't care what's in the block.
         */
        merge_freemem(ms);
+       if (need > PY_SSIZE_T_MAX / sizeof(PyObject*)) {
+               PyErr_NoMemory();
+               return -1;
+       }
        ms->a = (PyObject **)PyMem_Malloc(need * sizeof(PyObject*));
        if (ms->a) {
                ms->alloced = need;
@@ -2537,6 +2551,8 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
                                step = -step;
                        }
 
+                       assert(slicelength <= PY_SIZE_MAX / sizeof(PyObject*));
+
                        garbage = (PyObject**)
                                PyMem_MALLOC(slicelength*sizeof(PyObject*));
                        if (!garbage) {
index 840570e06cdd92be929a0221e5d1dba874c0928a..03add6b0893889bfb1dc9e5232194ab210c483b9 100644 (file)
@@ -526,9 +526,9 @@ new_arena(void)
                numarenas = maxarenas ? maxarenas << 1 : INITIAL_ARENA_OBJECTS;
                if (numarenas <= maxarenas)
                        return NULL;    /* overflow */
-               nbytes = numarenas * sizeof(*arenas);
-               if (nbytes / sizeof(*arenas) != numarenas)
+               if (numarenas > PY_SIZE_MAX / sizeof(*arenas))
                        return NULL;    /* overflow */
+               nbytes = numarenas * sizeof(*arenas);
                arenaobj = (struct arena_object *)realloc(arenas, nbytes);
                if (arenaobj == NULL)
                        return NULL;
index d133a0d17825118f9aad313ed7ba5f056669edf6..f4c86cb0ff5c836998fb765ffd1b9bf7bfe09659 100644 (file)
@@ -91,6 +91,9 @@ PyNode_AddChild(register node *n1, int type, char *str, int lineno, int col_offs
        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));
index 72329b9d2f26e7161b1c833854006b4f8df6e2e5..1105d3aa57b3cabf6b9964a791055dda74e25510 100644 (file)
@@ -5,8 +5,22 @@ asdl_seq *
 asdl_seq_new(int size, PyArena *arena)
 {
        asdl_seq *seq = NULL;
-       size_t n = sizeof(asdl_seq) +
-                       (size ? (sizeof(void *) * (size - 1)) : 0);
+       size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
+
+       /* check size is sane */
+       if (size < 0 || size == INT_MIN || 
+               (size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       /* check if size can be added safely */
+       if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       n += sizeof(asdl_seq);
 
        seq = (asdl_seq *)PyArena_Malloc(arena, n);
        if (!seq) {
@@ -22,8 +36,22 @@ asdl_int_seq *
 asdl_int_seq_new(int size, PyArena *arena)
 {
        asdl_int_seq *seq = NULL;
-       size_t n = sizeof(asdl_seq) +
-                       (size ? (sizeof(int) * (size - 1)) : 0);
+       size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
+
+       /* check size is sane */
+       if (size < 0 || size == INT_MIN || 
+               (size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
+                       PyErr_NoMemory();
+                       return NULL;
+       }
+
+       /* check if size can be added safely */
+       if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       n += sizeof(asdl_seq);
 
        seq = (asdl_int_seq *)PyArena_Malloc(arena, n);
        if (!seq) {
index 2c03ad6acf58fd6e6ef790599b0045370254ec64..3381260d0740d883deb9dad58381c54ce0181827 100644 (file)
@@ -3130,6 +3130,9 @@ decode_unicode(const char *s, size_t len, int rawmode, const char *encoding)
                buf = (char *)s;
                u = NULL;
        } else {
+               /* check for integer overflow */
+               if (len > PY_SIZE_MAX / 4)
+                       return NULL;
                /* "\XX" may become "\u005c\uHHLL" (12 bytes) */
                u = PyString_FromStringAndSize((char *)NULL, len * 4);
                if (u == NULL)
index f82430cba6fbdace0852b25f022d600478ca2e53..63f2f78e87f07dbf6257831cd8d4f66f9f9ab08c 100644 (file)
@@ -2496,11 +2496,43 @@ filterstring(PyObject *func, PyObject *strobj)
                                        PyString_AS_STRING(item)[0];
                        } else {
                                /* do we need more space? */
-                               Py_ssize_t need = j + reslen + len-i-1;
+                               Py_ssize_t need = j;
+
+                               /* calculate space requirements while checking for overflow */
+                               if (need > PY_SSIZE_T_MAX - reslen) {
+                                       Py_DECREF(item);
+                                       goto Fail_1;
+                               }
+
+                               need += reslen;
+
+                               if (need > PY_SSIZE_T_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 > PY_SSIZE_T_MAX / 2) {
+                                               Py_DECREF(item);
+                                               return NULL;
+                                       }
+
+                                       if (need<2*outlen) {
                                                need = 2*outlen;
+          }
                                        if (_PyString_Resize(&result, need)) {
                                                Py_DECREF(item);
                                                return NULL;
@@ -2592,11 +2624,31 @@ filterunicode(PyObject *func, PyObject *strobj)
                        else {
                                /* do we need more space? */
                                Py_ssize_t need = j + reslen + len - i - 1;
+        
+                               /* check that didnt overflow */
+                               if ((j > PY_SSIZE_T_MAX - reslen) ||
+                                       ((j + reslen) > PY_SSIZE_T_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 > PY_SSIZE_T_MAX / 2) {
+              Py_DECREF(item);
+              return NULL;
+                                               } else {
+                                                       need = 2 * outlen;
+                                   }
+          }
+
                                        if (PyUnicode_Resize(
                                                &result, need) < 0) {
                                                Py_DECREF(item);
index 4dfc42d92893147daa3cd3e2200548c994130494..f40c325bbfe69f0195be803b82b8604d79e93868 100644 (file)
@@ -225,6 +225,10 @@ _Py_Mangle(PyObject *privateobj, PyObject *ident)
                return ident; /* Don't mangle if class is just underscores */
        }
        plen = strlen(p);
+
+       assert(1 <= PY_SSIZE_T_MAX - nlen);
+       assert(1 + nlen <= PY_SSIZE_T_MAX - plen);
+
        ident = PyString_FromStringAndSize(NULL, 1 + nlen + plen);
        if (!ident)
                return 0;
@@ -620,6 +624,8 @@ markblocks(unsigned char *code, int len)
        unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
        int i,j, opcode, blockcnt = 0;
 
+       assert(len <= PY_SIZE_MAX / sizeof(int));
+
        if (blocks == NULL) {
                PyErr_NoMemory();
                return NULL;
@@ -1281,6 +1287,12 @@ compiler_next_instr(struct compiler *c, basicblock *b)
                size_t oldsize, newsize;
                oldsize = b->b_ialloc * sizeof(struct instr);
                newsize = oldsize << 1;
+
+               if (oldsize > (PY_SIZE_MAX >> 1)) {
+                       PyErr_NoMemory();
+                       return -1;
+               }
+
                if (newsize == 0) {
                        PyErr_NoMemory();
                        return -1;
@@ -4091,6 +4103,10 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno)
        a->a_lnotab = PyString_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
        if (!a->a_lnotab)
                return 0;
+       if (nblocks > PY_SIZE_MAX / sizeof(basicblock *)) {
+               PyErr_NoMemory();
+               return 0;
+       }
        a->a_postorder = (basicblock **)PyObject_Malloc(
                                            sizeof(basicblock *) * nblocks);
        if (!a->a_postorder) {
@@ -4199,10 +4215,14 @@ assemble_lnotab(struct assembler *a, struct instr *i)
                nbytes = a->a_lnotab_off + 2 * ncodes;
                len = PyString_GET_SIZE(a->a_lnotab);
                if (nbytes >= len) {
-                       if (len * 2 < nbytes)
+                       if ((len <= INT_MAX / 2) && (len * 2 < nbytes))
                                len = nbytes;
-                       else
+                       else if (len <= INT_MAX / 2)
                                len *= 2;
+                       else {
+                               PyErr_NoMemory();
+                               return 0;
+                       }
                        if (_PyString_Resize(&a->a_lnotab, len) < 0)
                                return 0;
                }
@@ -4221,10 +4241,14 @@ assemble_lnotab(struct assembler *a, struct instr *i)
                nbytes = a->a_lnotab_off + 2 * ncodes;
                len = PyString_GET_SIZE(a->a_lnotab);
                if (nbytes >= len) {
-                       if (len * 2 < nbytes)
+                       if ((len <= INT_MAX / 2) && len * 2 < nbytes)
                                len = nbytes;
-                       else
+                       else if (len <= INT_MAX / 2)
                                len *= 2;
+                       else {
+                               PyErr_NoMemory();
+                               return 0;
+                       }
                        if (_PyString_Resize(&a->a_lnotab, len) < 0)
                                return 0;
                }
@@ -4283,6 +4307,8 @@ assemble_emit(struct assembler *a, struct instr *i)
        if (i->i_lineno && !assemble_lnotab(a, i))
                return 0;
        if (a->a_offset + size >= len) {
+               if (len > PY_SSIZE_T_MAX / 2)
+                       return 0;
                if (_PyString_Resize(&a->a_bytecode, len * 2) < 0)
                    return 0;
        }