Merge in release25-maint 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.
diff --git a/Modules/_csv.c b/Modules/_csv.c
index c628927..a5787d3 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -559,6 +559,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);
}
@@ -1053,6 +1057,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;
diff --git a/Modules/_struct.c b/Modules/_struct.c
index e5fe211..078c3a5 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -1385,6 +1385,12 @@
}
}
+ /* 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 89ed27a..c505dad 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -652,6 +652,9 @@
PyErr_BadArgument();
return NULL;
}
+ if (Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b)) {
+ return PyErr_NoMemory();
+ }
size = Py_SIZE(a) + Py_SIZE(b);
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
if (np == NULL) {
@@ -674,6 +677,9 @@
Py_ssize_t nbytes;
if (n < 0)
n = 0;
+ if ((Py_SIZE(a) != 0) && (n > PY_SSIZE_T_MAX / Py_SIZE(a))) {
+ return PyErr_NoMemory();
+ }
size = Py_SIZE(a) * n;
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
if (np == NULL)
@@ -818,6 +824,11 @@
"can only extend with array of same kind");
return -1;
}
+ if ((Py_SIZE(self) > PY_SSIZE_T_MAX - Py_SIZE(b)) ||
+ ((Py_SIZE(self) + Py_SIZE(b)) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
+ PyErr_NoMemory();
+ return -1;
+ }
size = Py_SIZE(self) + Py_SIZE(b);
PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
if (self->ob_item == NULL) {
@@ -859,6 +870,10 @@
if (n < 0)
n = 0;
items = self->ob_item;
+ if ((self->ob_descr->itemsize != 0) &&
+ (Py_SIZE(self) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
+ return PyErr_NoMemory();
+ }
size = Py_SIZE(self) * self->ob_descr->itemsize;
if (n == 0) {
PyMem_FREE(items);
@@ -867,6 +882,9 @@
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 @@
Py_INCREF(dict);
}
if (Py_SIZE(array) > 0) {
+ if (array->ob_descr->itemsize
+ > PY_SSIZE_T_MAX / array->ob_size) {
+ return PyErr_NoMemory();
+ }
result = Py_BuildValue("O(cs#)O",
Py_TYPE(array),
array->ob_descr->typecode,
@@ -1330,6 +1352,9 @@
if ((*self->ob_descr->setitem)(self,
Py_SIZE(self) - n + i, v) != 0) {
Py_SIZE(self) -= n;
+ if (itemsize && (self->ob_size > PY_SSIZE_T_MAX / itemsize)) {
+ return PyErr_NoMemory();
+ }
PyMem_RESIZE(item, char,
Py_SIZE(self) * itemsize);
self->ob_item = item;
@@ -1389,6 +1414,10 @@
n = n / itemsize;
if (n > 0) {
char *item = self->ob_item;
+ if ((n > PY_SSIZE_T_MAX - Py_SIZE(self)) ||
+ ((Py_SIZE(self) + n) > PY_SSIZE_T_MAX / itemsize)) {
+ return PyErr_NoMemory();
+ }
PyMem_RESIZE(item, char, (Py_SIZE(self) + n) * itemsize);
if (item == NULL) {
PyErr_NoMemory();
@@ -1414,8 +1443,12 @@
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,
Py_SIZE(self) * self->ob_descr->itemsize);
+ } else {
+ return PyErr_NoMemory();
+ }
}
PyDoc_STRVAR(tostring_doc,
@@ -1443,6 +1476,9 @@
}
if (n > 0) {
Py_UNICODE *item = (Py_UNICODE *) self->ob_item;
+ if (Py_SIZE(self) > PY_SSIZE_T_MAX - n) {
+ return PyErr_NoMemory();
+ }
PyMem_RESIZE(item, Py_UNICODE, Py_SIZE(self) + n);
if (item == NULL) {
PyErr_NoMemory();
diff --git a/Modules/audioop.c b/Modules/audioop.c
index ce00975..31e3fa4 100644
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -829,7 +829,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;
@@ -846,7 +846,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);
@@ -1009,7 +1016,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;
@@ -1023,7 +1030,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);
@@ -1059,6 +1072,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;
@@ -1101,8 +1115,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;
@@ -1276,7 +1296,7 @@
unsigned char *cp;
unsigned char cval;
signed char *ncp;
- int len, size, val;
+ int len, new_len, size, val;
PyObject *rv;
int i;
@@ -1289,12 +1309,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_ulaw2linear16(cval);
@@ -1344,7 +1370,7 @@
unsigned char *cp;
unsigned char cval;
signed char *ncp;
- int len, size, val;
+ int len, new_len, size, val;
PyObject *rv;
int i;
@@ -1357,12 +1383,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_alaw2linear16(cval);
@@ -1487,7 +1519,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;
@@ -1509,7 +1541,13 @@
} 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);
@@ -1517,7 +1555,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;
diff --git a/Modules/binascii.c b/Modules/binascii.c
index c1fc675..bcbafcf 100644
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -141,7 +141,7 @@
#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+/";
@@ -198,6 +198,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--;
@@ -351,6 +353,11 @@
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 */
@@ -440,6 +447,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;
@@ -495,6 +505,11 @@
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. */
@@ -558,6 +573,11 @@
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;
@@ -607,6 +627,11 @@
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;
@@ -645,9 +670,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 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;
@@ -673,6 +702,7 @@
#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) \
@@ -741,7 +771,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++];
}
@@ -901,7 +931,7 @@
return NULL;
crc = ~ crc;
- while (len--)
+ while (len-- > 0)
crc = crc_32_tab[(crc ^ *bin_data++) & 0xffU] ^ (crc >> 8);
/* Note: (crc >> 8) MUST zero fill on left */
@@ -923,6 +953,10 @@
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;
@@ -980,6 +1014,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.
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index f130087..51fc226 100644
--- a/Modules/cPickle.c
+++ b/Modules/cPickle.c
@@ -3435,6 +3435,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;
@@ -3502,6 +3510,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;
diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c
index 139a4a8..237d8c2 100644
--- a/Modules/cStringIO.c
+++ b/Modules/cStringIO.c
@@ -119,6 +119,7 @@
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 @@
}
else
s=self->string_size;
+ assert(self->pos >= 0);
return PyString_FromStringAndSize(self->buf, s);
}
@@ -157,6 +159,8 @@
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 @@
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 @@
n -= m;
self->pos -= m;
}
+ assert(IOOOBJECT(self)->pos >= 0);
return PyString_FromStringAndSize(output, n);
}
@@ -277,6 +287,7 @@
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 bbd4c1a..a1b0ca9 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -163,13 +163,17 @@
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 @@
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;
@@ -735,6 +745,11 @@
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;
@@ -797,9 +812,10 @@
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;
@@ -1001,7 +1017,7 @@
PyObject *args, PyObject *kwargs)
{
MultibyteDecodeBuffer buf;
- char *data, *wdata;
+ char *data, *wdata = NULL;
Py_ssize_t wsize, finalsize = 0, size, origpending;
int final = 0;
@@ -1017,6 +1033,10 @@
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)
@@ -1235,6 +1255,10 @@
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 3443b42..fcbd2e9 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -1115,6 +1115,8 @@
char sign;
int none;
+ assert(buflen >= 1);
+
offset = call_utcoffset(tzinfo, tzinfoarg, &none);
if (offset == -1 && PyErr_Occurred())
return -1;
@@ -1206,6 +1208,11 @@
* a new format. Since computing the replacements for those codes
* is expensive, don't unless they're actually used.
*/
+ if (format_len > INT_MAX - 1) {
+ PyErr_NoMemory();
+ goto Done;
+ }
+
totalnew = format_len + 1; /* realistic if no %z/%Z/%f */
newfmt = PyString_FromStringAndSize(NULL, totalnew);
if (newfmt == NULL) goto Done;
diff --git a/Modules/md5.c b/Modules/md5.c
index c35d96c..0e1058f 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 @@
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/stropmodule.c b/Modules/stropmodule.c
index 8b00fed..bc60959 100644
--- a/Modules/stropmodule.c
+++ b/Modules/stropmodule.c
@@ -578,7 +578,7 @@
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 @@
}
/* 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 @@
}
}
+ 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)