summaryrefslogtreecommitdiff
path: root/Modules
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2008-02-14 11:26:18 +0000
committerMartin v. Löwis <martin@v.loewis.de>2008-02-14 11:26:18 +0000
commit27701ea6d05319c634182880325e6ae0d3f977d0 (patch)
treeabcbb14f1949188a0062ba9497220ff25798ea19 /Modules
parentf341b896b0a79a061ad2cca4eab818d6dee03d92 (diff)
downloadcpython-27701ea6d05319c634182880325e6ae0d3f977d0.tar.gz
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.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_csv.c10
-rw-r--r--Modules/_struct.c6
-rw-r--r--Modules/arraymodule.c38
-rw-r--r--Modules/audioop.c68
-rw-r--r--Modules/binascii.c42
-rw-r--r--Modules/cPickle.c16
-rw-r--r--Modules/cStringIO.c15
-rw-r--r--Modules/cjkcodecs/multibytecodec.c38
-rw-r--r--Modules/datetimemodule.c7
-rw-r--r--Modules/md5.c13
-rw-r--r--Modules/rgbimgmodule.c34
-rw-r--r--Modules/stropmodule.c19
12 files changed, 269 insertions, 37 deletions
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 5e03635597..2cd91998e1 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -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;
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 53c64848b1..41183fa26b 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -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));
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 3ba5cf88e1..da6e88f129 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -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();
diff --git a/Modules/audioop.c b/Modules/audioop.c
index 8f5d30c805..04355c17b0 100644
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -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;
diff --git a/Modules/binascii.c b/Modules/binascii.c
index 00f950d19d..fa22146668 100644
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -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.
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index b552a4033a..537276c82c 100644
--- a/Modules/cPickle.c
+++ b/Modules/cPickle.c
@@ -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;
diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c
index a6fad9cbf3..8fbb4f9af6 100644
--- a/Modules/cStringIO.c
+++ b/Modules/cStringIO.c
@@ -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);
}
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index 9fb9570225..8a2b660783 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -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)
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index a67c35de4e..34112c01d4 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -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;
diff --git a/Modules/md5.c b/Modules/md5.c
index c35d96c5ef..0e1058f5cc 100644
--- a/Modules/md5.c
+++ b/Modules/md5.c
@@ -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;
diff --git a/Modules/rgbimgmodule.c b/Modules/rgbimgmodule.c
index 0f9ee71f24..3eb2f5534f 100644
--- a/Modules/rgbimgmodule.c
+++ b/Modules/rgbimgmodule.c
@@ -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) {
diff --git a/Modules/stropmodule.c b/Modules/stropmodule.c
index 8b00fed69a..bc609590d4 100644
--- a/Modules/stropmodule.c
+++ b/Modules/stropmodule.c
@@ -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)