Commit 73c01d41 authored by Martin v. Löwis's avatar Martin v. Löwis

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.
parent abcb59a1
...@@ -83,14 +83,18 @@ PyAPI_FUNC(void) PyMem_Free(void *); ...@@ -83,14 +83,18 @@ PyAPI_FUNC(void) PyMem_Free(void *);
*/ */
#define PyMem_New(type, n) \ #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) \ #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) \ #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) \ #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 /* 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. * anymore. They're just confusing aliases for PyMem_{Free,FREE} now.
......
...@@ -117,6 +117,17 @@ typedef Py_intptr_t Py_ssize_t; ...@@ -117,6 +117,17 @@ typedef Py_intptr_t Py_ssize_t;
# error "Python needs a typedef for Py_ssize_t in pyport.h." # error "Python needs a typedef for Py_ssize_t in pyport.h."
#endif #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. */ /* Largest positive value of type Py_ssize_t. */
#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))
/* Smallest negative value of type Py_ssize_t. */ /* Smallest negative value of type Py_ssize_t. */
......
...@@ -975,6 +975,23 @@ tests.append(FloatTest) ...@@ -975,6 +975,23 @@ tests.append(FloatTest)
class DoubleTest(FPTest): class DoubleTest(FPTest):
typecode = 'd' typecode = 'd'
minitemsize = 8 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) tests.append(DoubleTest)
def test_main(verbose=None): def test_main(verbose=None):
......
...@@ -618,8 +618,12 @@ def test_unpack_with_buffer(): ...@@ -618,8 +618,12 @@ def test_unpack_with_buffer():
value, = struct.unpack('>I', data) value, = struct.unpack('>I', data)
vereq(value, 0x12345678) vereq(value, 0x12345678)
def test_crasher():
assertRaises(MemoryError, struct.pack, "357913941c", "a")
# Test methods to pack and unpack from buffers rather than strings. # Test methods to pack and unpack from buffers rather than strings.
test_unpack_from() test_unpack_from()
test_pack_into() test_pack_into()
test_pack_into_fn() test_pack_into_fn()
test_unpack_with_buffer() test_unpack_with_buffer()
test_crasher()
...@@ -12,6 +12,10 @@ What's New in Python 2.5.2c1? ...@@ -12,6 +12,10 @@ What's New in Python 2.5.2c1?
Core and builtins 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 - Issue #2045: Fix an infinite recursion triggered when printing a subclass of
collections.defaultdict, if its default_factory is set to a bound method. collections.defaultdict, if its default_factory is set to a bound method.
......
...@@ -560,6 +560,10 @@ parse_grow_buff(ReaderObj *self) ...@@ -560,6 +560,10 @@ parse_grow_buff(ReaderObj *self)
self->field = PyMem_Malloc(self->field_size); self->field = PyMem_Malloc(self->field_size);
} }
else { else {
if (self->field_size > INT_MAX / 2) {
PyErr_NoMemory();
return 0;
}
self->field_size *= 2; self->field_size *= 2;
self->field = PyMem_Realloc(self->field, self->field_size); self->field = PyMem_Realloc(self->field, self->field_size);
} }
...@@ -1055,6 +1059,12 @@ join_append_data(WriterObj *self, char *field, int quote_empty, ...@@ -1055,6 +1059,12 @@ join_append_data(WriterObj *self, char *field, int quote_empty,
static int static int
join_check_rec_size(WriterObj *self, int rec_len) 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 (rec_len > self->rec_size) {
if (self->rec_size == 0) { if (self->rec_size == 0) {
self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR; self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;
......
...@@ -1336,6 +1336,12 @@ prepare_s(PyStructObject *self) ...@@ -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_size = size;
self->s_len = len; self->s_len = len;
codes = PyMem_MALLOC((len + 1) * sizeof(formatcode)); codes = PyMem_MALLOC((len + 1) * sizeof(formatcode));
......
...@@ -652,6 +652,9 @@ array_concat(arrayobject *a, PyObject *bb) ...@@ -652,6 +652,9 @@ array_concat(arrayobject *a, PyObject *bb)
PyErr_BadArgument(); PyErr_BadArgument();
return NULL; return NULL;
} }
if (a->ob_size > PY_SSIZE_T_MAX - b->ob_size) {
return PyErr_NoMemory();
}
size = a->ob_size + b->ob_size; size = a->ob_size + b->ob_size;
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
if (np == NULL) { if (np == NULL) {
...@@ -674,6 +677,9 @@ array_repeat(arrayobject *a, Py_ssize_t n) ...@@ -674,6 +677,9 @@ array_repeat(arrayobject *a, Py_ssize_t n)
Py_ssize_t nbytes; Py_ssize_t nbytes;
if (n < 0) if (n < 0)
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; size = a->ob_size * n;
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
if (np == NULL) if (np == NULL)
...@@ -818,6 +824,11 @@ array_do_extend(arrayobject *self, PyObject *bb) ...@@ -818,6 +824,11 @@ array_do_extend(arrayobject *self, PyObject *bb)
"can only extend with array of same kind"); "can only extend with array of same kind");
return -1; 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; size = self->ob_size + b->ob_size;
PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize); PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
if (self->ob_item == NULL) { if (self->ob_item == NULL) {
...@@ -859,6 +870,10 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n) ...@@ -859,6 +870,10 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
if (n < 0) if (n < 0)
n = 0; n = 0;
items = self->ob_item; 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; size = self->ob_size * self->ob_descr->itemsize;
if (n == 0) { if (n == 0) {
PyMem_FREE(items); PyMem_FREE(items);
...@@ -867,6 +882,9 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n) ...@@ -867,6 +882,9 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
self->allocated = 0; self->allocated = 0;
} }
else { else {
if (size > PY_SSIZE_T_MAX / n) {
return PyErr_NoMemory();
}
PyMem_Resize(items, char, n * size); PyMem_Resize(items, char, n * size);
if (items == NULL) if (items == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
...@@ -1148,6 +1166,10 @@ array_reduce(arrayobject *array) ...@@ -1148,6 +1166,10 @@ array_reduce(arrayobject *array)
Py_INCREF(dict); Py_INCREF(dict);
} }
if (array->ob_size > 0) { 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", result = Py_BuildValue("O(cs#)O",
array->ob_type, array->ob_type,
array->ob_descr->typecode, array->ob_descr->typecode,
...@@ -1310,6 +1332,9 @@ array_fromlist(arrayobject *self, PyObject *list) ...@@ -1310,6 +1332,9 @@ array_fromlist(arrayobject *self, PyObject *list)
if ((*self->ob_descr->setitem)(self, if ((*self->ob_descr->setitem)(self,
self->ob_size - n + i, v) != 0) { self->ob_size - n + i, v) != 0) {
self->ob_size -= n; self->ob_size -= n;
if (itemsize && (self->ob_size > PY_SSIZE_T_MAX / itemsize)) {
return PyErr_NoMemory();
}
PyMem_RESIZE(item, char, PyMem_RESIZE(item, char,
self->ob_size * itemsize); self->ob_size * itemsize);
self->ob_item = item; self->ob_item = item;
...@@ -1369,6 +1394,10 @@ array_fromstring(arrayobject *self, PyObject *args) ...@@ -1369,6 +1394,10 @@ array_fromstring(arrayobject *self, PyObject *args)
n = n / itemsize; n = n / itemsize;
if (n > 0) { if (n > 0) {
char *item = self->ob_item; 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); PyMem_RESIZE(item, char, (self->ob_size + n) * itemsize);
if (item == NULL) { if (item == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
...@@ -1394,8 +1423,12 @@ values,as if it had been read from a file using the fromfile() method)."); ...@@ -1394,8 +1423,12 @@ values,as if it had been read from a file using the fromfile() method).");
static PyObject * static PyObject *
array_tostring(arrayobject *self, PyObject *unused) 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); self->ob_size * self->ob_descr->itemsize);
} else {
return PyErr_NoMemory();
}
} }
PyDoc_STRVAR(tostring_doc, PyDoc_STRVAR(tostring_doc,
...@@ -1423,6 +1456,9 @@ array_fromunicode(arrayobject *self, PyObject *args) ...@@ -1423,6 +1456,9 @@ array_fromunicode(arrayobject *self, PyObject *args)
} }
if (n > 0) { if (n > 0) {
Py_UNICODE *item = (Py_UNICODE *) self->ob_item; 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); PyMem_RESIZE(item, Py_UNICODE, self->ob_size + n);
if (item == NULL) { if (item == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
......
...@@ -824,7 +824,7 @@ static PyObject * ...@@ -824,7 +824,7 @@ static PyObject *
audioop_tostereo(PyObject *self, PyObject *args) audioop_tostereo(PyObject *self, PyObject *args)
{ {
signed char *cp, *ncp; 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; double fac1, fac2, fval, maxval;
PyObject *rv; PyObject *rv;
int i; int i;
...@@ -841,7 +841,14 @@ audioop_tostereo(PyObject *self, PyObject *args) ...@@ -841,7 +841,14 @@ audioop_tostereo(PyObject *self, PyObject *args)
return 0; 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 ) if ( rv == 0 )
return 0; return 0;
ncp = (signed char *)PyString_AsString(rv); ncp = (signed char *)PyString_AsString(rv);
...@@ -1004,7 +1011,7 @@ audioop_lin2lin(PyObject *self, PyObject *args) ...@@ -1004,7 +1011,7 @@ audioop_lin2lin(PyObject *self, PyObject *args)
{ {
signed char *cp; signed char *cp;
unsigned char *ncp; unsigned char *ncp;
int len, size, size2, val = 0; int len, new_len, size, size2, val = 0;
PyObject *rv; PyObject *rv;
int i, j; int i, j;
...@@ -1018,7 +1025,13 @@ audioop_lin2lin(PyObject *self, PyObject *args) ...@@ -1018,7 +1025,13 @@ audioop_lin2lin(PyObject *self, PyObject *args)
return 0; 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 ) if ( rv == 0 )
return 0; return 0;
ncp = (unsigned char *)PyString_AsString(rv); ncp = (unsigned char *)PyString_AsString(rv);
...@@ -1054,6 +1067,7 @@ audioop_ratecv(PyObject *self, PyObject *args) ...@@ -1054,6 +1067,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
int chan, d, *prev_i, *cur_i, cur_o; int chan, d, *prev_i, *cur_i, cur_o;
PyObject *state, *samps, *str, *rv = NULL; PyObject *state, *samps, *str, *rv = NULL;
int bytes_per_frame; int bytes_per_frame;
size_t alloc_size;
weightA = 1; weightA = 1;
weightB = 0; weightB = 0;
...@@ -1096,8 +1110,14 @@ audioop_ratecv(PyObject *self, PyObject *args) ...@@ -1096,8 +1110,14 @@ audioop_ratecv(PyObject *self, PyObject *args)
inrate /= d; inrate /= d;
outrate /= d; outrate /= d;
prev_i = (int *) malloc(nchannels * sizeof(int)); alloc_size = sizeof(int) * (unsigned)nchannels;
cur_i = (int *) malloc(nchannels * sizeof(int)); 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) { if (prev_i == NULL || cur_i == NULL) {
(void) PyErr_NoMemory(); (void) PyErr_NoMemory();
goto exit; goto exit;
...@@ -1271,7 +1291,7 @@ audioop_ulaw2lin(PyObject *self, PyObject *args) ...@@ -1271,7 +1291,7 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
unsigned char *cp; unsigned char *cp;
unsigned char cval; unsigned char cval;
signed char *ncp; signed char *ncp;
int len, size, val; int len, new_len, size, val;
PyObject *rv; PyObject *rv;
int i; int i;
...@@ -1284,12 +1304,18 @@ audioop_ulaw2lin(PyObject *self, PyObject *args) ...@@ -1284,12 +1304,18 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
return 0; 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 ) if ( rv == 0 )
return 0; return 0;
ncp = (signed char *)PyString_AsString(rv); ncp = (signed char *)PyString_AsString(rv);
for ( i=0; i < len*size; i += size ) { for ( i=0; i < new_len; i += size ) {
cval = *cp++; cval = *cp++;
val = st_ulaw2linear16(cval); val = st_ulaw2linear16(cval);
...@@ -1339,7 +1365,7 @@ audioop_alaw2lin(PyObject *self, PyObject *args) ...@@ -1339,7 +1365,7 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
unsigned char *cp; unsigned char *cp;
unsigned char cval; unsigned char cval;
signed char *ncp; signed char *ncp;
int len, size, val; int len, new_len, size, val;
PyObject *rv; PyObject *rv;
int i; int i;
...@@ -1352,12 +1378,18 @@ audioop_alaw2lin(PyObject *self, PyObject *args) ...@@ -1352,12 +1378,18 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
return 0; 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 ) if ( rv == 0 )
return 0; return 0;
ncp = (signed char *)PyString_AsString(rv); ncp = (signed char *)PyString_AsString(rv);
for ( i=0; i < len*size; i += size ) { for ( i=0; i < new_len; i += size ) {
cval = *cp++; cval = *cp++;
val = st_alaw2linear16(cval); val = st_alaw2linear16(cval);
...@@ -1482,7 +1514,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args) ...@@ -1482,7 +1514,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
{ {
signed char *cp; signed char *cp;
signed char *ncp; 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; PyObject *rv, *str, *state;
int i, inputbuffer = 0, bufferstep; int i, inputbuffer = 0, bufferstep;
...@@ -1504,7 +1536,13 @@ audioop_adpcm2lin(PyObject *self, PyObject *args) ...@@ -1504,7 +1536,13 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
} else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) ) } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) )
return 0; 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 ) if ( str == 0 )
return 0; return 0;
ncp = (signed char *)PyString_AsString(str); ncp = (signed char *)PyString_AsString(str);
...@@ -1512,7 +1550,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args) ...@@ -1512,7 +1550,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
step = stepsizeTable[index]; step = stepsizeTable[index];
bufferstep = 0; 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 */ /* Step 1 - get the delta value and compute next index */
if ( bufferstep ) { if ( bufferstep ) {
delta = inputbuffer & 0xf; delta = inputbuffer & 0xf;
......
...@@ -138,7 +138,7 @@ static char table_a2b_base64[] = { ...@@ -138,7 +138,7 @@ static char table_a2b_base64[] = {
#define BASE64_PAD '=' #define BASE64_PAD '='
/* Max binary chunk size; limited only by available memory */ /* 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[] = static unsigned char table_b2a_base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
...@@ -195,6 +195,8 @@ binascii_a2b_uu(PyObject *self, PyObject *args) ...@@ -195,6 +195,8 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) ) if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) )
return NULL; return NULL;
assert(ascii_len >= 0);
/* First byte: binary data length (in bytes) */ /* First byte: binary data length (in bytes) */
bin_len = (*ascii_data++ - ' ') & 077; bin_len = (*ascii_data++ - ' ') & 077;
ascii_len--; ascii_len--;
...@@ -348,6 +350,11 @@ binascii_a2b_base64(PyObject *self, PyObject *args) ...@@ -348,6 +350,11 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) ) if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) )
return NULL; 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 */ bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
/* Allocate the buffer */ /* Allocate the buffer */
...@@ -437,6 +444,9 @@ binascii_b2a_base64(PyObject *self, PyObject *args) ...@@ -437,6 +444,9 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) ) if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) )
return NULL; return NULL;
assert(bin_len >= 0);
if ( bin_len > BASE64_MAXBIN ) { if ( bin_len > BASE64_MAXBIN ) {
PyErr_SetString(Error, "Too much data for base64 line"); PyErr_SetString(Error, "Too much data for base64 line");
return NULL; return NULL;
...@@ -492,6 +502,11 @@ binascii_a2b_hqx(PyObject *self, PyObject *args) ...@@ -492,6 +502,11 @@ binascii_a2b_hqx(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) ) if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) )
return NULL; return NULL;
assert(len >= 0);
if (len > PY_SSIZE_T_MAX - 2)
return PyErr_NoMemory();
/* Allocate a string that is too big (fixed later) /* Allocate a string that is too big (fixed later)
Add two to the initial length to prevent interning which Add two to the initial length to prevent interning which
would preclude subsequent resizing. */ would preclude subsequent resizing. */
...@@ -555,6 +570,11 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args) ...@@ -555,6 +570,11 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) ) if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) )
return NULL; 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) */ /* Worst case: output is twice as big as input (fixed later) */
if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL ) if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL )
return NULL; return NULL;
...@@ -604,6 +624,11 @@ binascii_b2a_hqx(PyObject *self, PyObject *args) ...@@ -604,6 +624,11 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) ) if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) )
return NULL; 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 */ /* Allocate a buffer that is at least large enough */
if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL ) if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL )
return NULL; return NULL;
...@@ -642,9 +667,13 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args) ...@@ -642,9 +667,13 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "s#:rledecode_hqx", &in_data, &in_len) ) if ( !PyArg_ParseTuple(args, "s#:rledecode_hqx", &in_data, &in_len) )
return NULL; return NULL;
assert(in_len >= 0);
/* Empty string is a special case */ /* Empty string is a special case */
if ( in_len == 0 ) if ( in_len == 0 )
return PyString_FromString(""); return PyString_FromString("");
else if (in_len > PY_SSIZE_T_MAX / 2)
return PyErr_NoMemory();
/* Allocate a buffer of reasonable size. Resized when needed */ /* Allocate a buffer of reasonable size. Resized when needed */
out_len = in_len*2; out_len = in_len*2;
...@@ -670,6 +699,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args) ...@@ -670,6 +699,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
#define OUTBYTE(b) \ #define OUTBYTE(b) \
do { \ do { \
if ( --out_len_left < 0 ) { \ if ( --out_len_left < 0 ) { \
if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \
_PyString_Resize(&rv, 2*out_len); \ _PyString_Resize(&rv, 2*out_len); \
if ( rv == NULL ) return NULL; \ if ( rv == NULL ) return NULL; \
out_data = (unsigned char *)PyString_AsString(rv) \ out_data = (unsigned char *)PyString_AsString(rv) \
...@@ -738,7 +768,7 @@ binascii_crc_hqx(PyObject *self, PyObject *args) ...@@ -738,7 +768,7 @@ binascii_crc_hqx(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) ) if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) )
return NULL; return NULL;
while(len--) { while(len-- > 0) {
crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++]; crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++];
} }
...@@ -882,7 +912,7 @@ binascii_crc32(PyObject *self, PyObject *args) ...@@ -882,7 +912,7 @@ binascii_crc32(PyObject *self, PyObject *args)
/* only want the trailing 32 bits */ /* only want the trailing 32 bits */
crc &= 0xFFFFFFFFUL; crc &= 0xFFFFFFFFUL;
#endif #endif
while (len--) while (len-- > 0)
crc = crc_32_tab[(crc ^ *bin_data++) & 0xffUL] ^ (crc >> 8); crc = crc_32_tab[(crc ^ *bin_data++) & 0xffUL] ^ (crc >> 8);
/* Note: (crc >> 8) MUST zero fill on left */ /* Note: (crc >> 8) MUST zero fill on left */
...@@ -912,6 +942,10 @@ binascii_hexlify(PyObject *self, PyObject *args) ...@@ -912,6 +942,10 @@ binascii_hexlify(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen)) if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen))
return NULL; return NULL;
assert(arglen >= 0);
if (arglen > PY_SSIZE_T_MAX / 2)
return PyErr_NoMemory();
retval = PyString_FromStringAndSize(NULL, arglen*2); retval = PyString_FromStringAndSize(NULL, arglen*2);
if (!retval) if (!retval)
return NULL; return NULL;
...@@ -969,6 +1003,8 @@ binascii_unhexlify(PyObject *self, PyObject *args) ...@@ -969,6 +1003,8 @@ binascii_unhexlify(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen)) if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen))
return NULL; return NULL;
assert(arglen >= 0);
/* XXX What should we do about strings with an odd length? Should /* XXX What should we do about strings with an odd length? Should
* we add an implicit leading zero, or a trailing zero? For now, * we add an implicit leading zero, or a trailing zero? For now,
* raise an exception. * raise an exception.
......
...@@ -3432,6 +3432,14 @@ load_binstring(Unpicklerobject *self) ...@@ -3432,6 +3432,14 @@ load_binstring(Unpicklerobject *self)
if (self->read_func(self, &s, 4) < 0) return -1; if (self->read_func(self, &s, 4) < 0) return -1;
l = calc_binint(s, 4); 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) if (self->read_func(self, &s, l) < 0)
return -1; return -1;
...@@ -3499,6 +3507,14 @@ load_binunicode(Unpicklerobject *self) ...@@ -3499,6 +3507,14 @@ load_binunicode(Unpicklerobject *self)
if (self->read_func(self, &s, 4) < 0) return -1; if (self->read_func(self, &s, 4) < 0) return -1;
l = calc_binint(s, 4); 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) if (self->read_func(self, &s, l) < 0)
return -1; return -1;
......
...@@ -119,6 +119,7 @@ PyDoc_STRVAR(IO_getval__doc__, ...@@ -119,6 +119,7 @@ PyDoc_STRVAR(IO_getval__doc__,
static PyObject * static PyObject *
IO_cgetval(PyObject *self) { IO_cgetval(PyObject *self) {
if (!IO__opencheck(IOOOBJECT(self))) return NULL; if (!IO__opencheck(IOOOBJECT(self))) return NULL;
assert(IOOOBJECT(self)->pos >= 0);
return PyString_FromStringAndSize(((IOobject*)self)->buf, return PyString_FromStringAndSize(((IOobject*)self)->buf,
((IOobject*)self)->pos); ((IOobject*)self)->pos);
} }
...@@ -137,6 +138,7 @@ IO_getval(IOobject *self, PyObject *args) { ...@@ -137,6 +138,7 @@ IO_getval(IOobject *self, PyObject *args) {
} }
else else
s=self->string_size; s=self->string_size;
assert(self->pos >= 0);
return PyString_FromStringAndSize(self->buf, s); return PyString_FromStringAndSize(self->buf, s);
} }
...@@ -157,6 +159,8 @@ IO_cread(PyObject *self, char **output, Py_ssize_t n) { ...@@ -157,6 +159,8 @@ IO_cread(PyObject *self, char **output, Py_ssize_t n) {
Py_ssize_t l; Py_ssize_t l;
if (!IO__opencheck(IOOOBJECT(self))) return -1; 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; l = ((IOobject*)self)->string_size - ((IOobject*)self)->pos;
if (n < 0 || n > l) { if (n < 0 || n > l) {
n = l; n = l;
...@@ -192,12 +196,17 @@ IO_creadline(PyObject *self, char **output) { ...@@ -192,12 +196,17 @@ IO_creadline(PyObject *self, char **output) {
for (n = ((IOobject*)self)->buf + ((IOobject*)self)->pos, for (n = ((IOobject*)self)->buf + ((IOobject*)self)->pos,
s = ((IOobject*)self)->buf + ((IOobject*)self)->string_size; s = ((IOobject*)self)->buf + ((IOobject*)self)->string_size;
n < s && *n != '\n'; n++); n < s && *n != '\n'; n++);
if (n < s) n++; if (n < s) n++;
*output=((IOobject*)self)->buf + ((IOobject*)self)->pos; *output=((IOobject*)self)->buf + ((IOobject*)self)->pos;
l = n - ((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; return (int)l;
} }
...@@ -215,6 +224,7 @@ IO_readline(IOobject *self, PyObject *args) { ...@@ -215,6 +224,7 @@ IO_readline(IOobject *self, PyObject *args) {
n -= m; n -= m;
self->pos -= m; self->pos -= m;
} }
assert(IOOOBJECT(self)->pos >= 0);
return PyString_FromStringAndSize(output, n); return PyString_FromStringAndSize(output, n);
} }
...@@ -277,6 +287,7 @@ IO_tell(IOobject *self, PyObject *unused) { ...@@ -277,6 +287,7 @@ IO_tell(IOobject *self, PyObject *unused) {
if (!IO__opencheck(self)) return NULL; if (!IO__opencheck(self)) return NULL;
assert(self->pos >= 0);
return PyInt_FromSsize_t(self->pos); return PyInt_FromSsize_t(self->pos);
} }
......
...@@ -163,13 +163,17 @@ static PyGetSetDef codecctx_getsets[] = { ...@@ -163,13 +163,17 @@ static PyGetSetDef codecctx_getsets[] = {
static int static int
expand_encodebuffer(MultibyteEncodeBuffer *buf, Py_ssize_t esize) 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 - orgpos = (Py_ssize_t)((char *)buf->outbuf -
PyString_AS_STRING(buf->outobj)); PyString_AS_STRING(buf->outobj));
orgsize = PyString_GET_SIZE(buf->outobj); orgsize = PyString_GET_SIZE(buf->outobj);
if (_PyString_Resize(&buf->outobj, orgsize + ( incsize = (esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize);
esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize)) == -1)
if (orgsize > PY_SSIZE_T_MAX - incsize)
return -1;
if (_PyString_Resize(&buf->outobj, orgsize + incsize) == -1)
return -1; return -1;
buf->outbuf = (unsigned char *)PyString_AS_STRING(buf->outobj) +orgpos; buf->outbuf = (unsigned char *)PyString_AS_STRING(buf->outobj) +orgpos;
...@@ -473,6 +477,12 @@ multibytecodec_encode(MultibyteCodec *codec, ...@@ -473,6 +477,12 @@ multibytecodec_encode(MultibyteCodec *codec,
buf.excobj = NULL; buf.excobj = NULL;
buf.inbuf = buf.inbuf_top = *data; buf.inbuf = buf.inbuf_top = *data;
buf.inbuf_end = buf.inbuf_top + datalen; 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); buf.outobj = PyString_FromStringAndSize(NULL, datalen * 2 + 16);
if (buf.outobj == NULL) if (buf.outobj == NULL)
goto errorexit; goto errorexit;
...@@ -736,6 +746,11 @@ encoder_encode_stateful(MultibyteStatefulEncoderContext *ctx, ...@@ -736,6 +746,11 @@ encoder_encode_stateful(MultibyteStatefulEncoderContext *ctx,
origpending = ctx->pendingsize; origpending = ctx->pendingsize;
if (origpending > 0) { 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); inbuf_tmp = PyMem_New(Py_UNICODE, datalen + ctx->pendingsize);
if (inbuf_tmp == NULL) if (inbuf_tmp == NULL)
goto errorexit; goto errorexit;
...@@ -798,9 +813,10 @@ decoder_append_pending(MultibyteStatefulDecoderContext *ctx, ...@@ -798,9 +813,10 @@ decoder_append_pending(MultibyteStatefulDecoderContext *ctx,
Py_ssize_t npendings; Py_ssize_t npendings;
npendings = (Py_ssize_t)(buf->inbuf_end - buf->inbuf); npendings = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
if (npendings + ctx->pendingsize > MAXDECPENDING) { if (npendings + ctx->pendingsize > MAXDECPENDING ||
PyErr_SetString(PyExc_UnicodeError, "pending buffer overflow"); npendings > PY_SSIZE_T_MAX - ctx->pendingsize) {
return -1; PyErr_SetString(PyExc_UnicodeError, "pending buffer overflow");
return -1;
} }
memcpy(ctx->pending + ctx->pendingsize, buf->inbuf, npendings); memcpy(ctx->pending + ctx->pendingsize, buf->inbuf, npendings);
ctx->pendingsize += npendings; ctx->pendingsize += npendings;
...@@ -1003,7 +1019,7 @@ mbidecoder_decode(MultibyteIncrementalDecoderObject *self, ...@@ -1003,7 +1019,7 @@ mbidecoder_decode(MultibyteIncrementalDecoderObject *self,
PyObject *args, PyObject *kwargs) PyObject *args, PyObject *kwargs)
{ {
MultibyteDecodeBuffer buf; MultibyteDecodeBuffer buf;
char *data, *wdata; char *data, *wdata = NULL;
Py_ssize_t wsize, finalsize = 0, size, origpending; Py_ssize_t wsize, finalsize = 0, size, origpending;
int final = 0; int final = 0;
...@@ -1019,6 +1035,10 @@ mbidecoder_decode(MultibyteIncrementalDecoderObject *self, ...@@ -1019,6 +1035,10 @@ mbidecoder_decode(MultibyteIncrementalDecoderObject *self,
wdata = data; wdata = data;
} }
else { else {
if (size > PY_SSIZE_T_MAX - self->pendingsize) {
PyErr_NoMemory();
goto errorexit;
}
wsize = size + self->pendingsize; wsize = size + self->pendingsize;
wdata = PyMem_Malloc(wsize); wdata = PyMem_Malloc(wsize);
if (wdata == NULL) if (wdata == NULL)
...@@ -1238,6 +1258,10 @@ mbstreamreader_iread(MultibyteStreamReaderObject *self, ...@@ -1238,6 +1258,10 @@ mbstreamreader_iread(MultibyteStreamReaderObject *self,
PyObject *ctr; PyObject *ctr;
char *ctrdata; char *ctrdata;
if (PyString_GET_SIZE(cres) > PY_SSIZE_T_MAX - self->pendingsize) {
PyErr_NoMemory();
goto errorexit;
}
rsize = PyString_GET_SIZE(cres) + self->pendingsize; rsize = PyString_GET_SIZE(cres) + self->pendingsize;
ctr = PyString_FromStringAndSize(NULL, rsize); ctr = PyString_FromStringAndSize(NULL, rsize);
if (ctr == NULL) if (ctr == NULL)
......
...@@ -1113,6 +1113,8 @@ format_utcoffset(char *buf, size_t buflen, const char *sep, ...@@ -1113,6 +1113,8 @@ format_utcoffset(char *buf, size_t buflen, const char *sep,
char sign; char sign;
int none; int none;
assert(buflen >= 1);
offset = call_utcoffset(tzinfo, tzinfoarg, &none); offset = call_utcoffset(tzinfo, tzinfoarg, &none);
if (offset == -1 && PyErr_Occurred()) if (offset == -1 && PyErr_Occurred())
return -1; return -1;
...@@ -1190,6 +1192,11 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, ...@@ -1190,6 +1192,11 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
* a new format. Since computing the replacements for those codes * a new format. Since computing the replacements for those codes
* is expensive, don't unless they're actually used. * 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 */ totalnew = PyString_Size(format) + 1; /* realistic if no %z/%Z */
newfmt = PyString_FromStringAndSize(NULL, totalnew); newfmt = PyString_FromStringAndSize(NULL, totalnew);
if (newfmt == NULL) goto Done; if (newfmt == NULL) goto Done;
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "md5.h" #include "md5.h"
#include <string.h> #include <string.h>
#include <limits.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN #ifdef ARCH_IS_BIG_ENDIAN
...@@ -330,6 +331,18 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) ...@@ -330,6 +331,18 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
if (nbytes <= 0) if (nbytes <= 0)
return; 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. */ /* Update the message length. */
pms->count[1] += nbytes >> 29; pms->count[1] += nbytes >> 29;
pms->count[0] += nbits; pms->count[0] += nbits;
......
...@@ -269,7 +269,7 @@ longimagedata(PyObject *self, PyObject *args) ...@@ -269,7 +269,7 @@ longimagedata(PyObject *self, PyObject *args)
Py_Int32 *starttab = NULL, *lengthtab = NULL; Py_Int32 *starttab = NULL, *lengthtab = NULL;
FILE *inf = NULL; FILE *inf = NULL;
IMAGE image; IMAGE image;
int y, z, tablen; int y, z, tablen, new_size;
int xsize, ysize, zsize; int xsize, ysize, zsize;
int bpp, rle, cur, badorder; int bpp, rle, cur, badorder;
int rlebuflen; int rlebuflen;
...@@ -301,9 +301,15 @@ longimagedata(PyObject *self, PyObject *args) ...@@ -301,9 +301,15 @@ longimagedata(PyObject *self, PyObject *args)
zsize = image.zsize; zsize = image.zsize;
if (rle) { if (rle) {
tablen = ysize * zsize * sizeof(Py_Int32); 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); starttab = (Py_Int32 *)malloc(tablen);
lengthtab = (Py_Int32 *)malloc(tablen); lengthtab = (Py_Int32 *)malloc(tablen);
rlebuflen = (int) (1.05 * xsize +10);
rledat = (unsigned char *)malloc(rlebuflen); rledat = (unsigned char *)malloc(rlebuflen);
if (!starttab || !lengthtab || !rledat) { if (!starttab || !lengthtab || !rledat) {
PyErr_NoMemory(); PyErr_NoMemory();
...@@ -331,8 +337,14 @@ longimagedata(PyObject *self, PyObject *args) ...@@ -331,8 +337,14 @@ longimagedata(PyObject *self, PyObject *args)
fseek(inf, 512 + 2 * tablen, SEEK_SET); fseek(inf, 512 + 2 * tablen, SEEK_SET);
cur = 512 + 2 * tablen; 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, rv = PyString_FromStringAndSize((char *)NULL,
(xsize * ysize + TAGLEN) * sizeof(Py_Int32)); new_size * sizeof(Py_Int32));
if (rv == NULL) if (rv == NULL)
goto finally; goto finally;
...@@ -400,8 +412,14 @@ longimagedata(PyObject *self, PyObject *args) ...@@ -400,8 +412,14 @@ longimagedata(PyObject *self, PyObject *args)
copybw((Py_Int32 *) base, xsize * ysize); copybw((Py_Int32 *) base, xsize * ysize);
} }
else { 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, rv = PyString_FromStringAndSize((char *) 0,
(xsize*ysize+TAGLEN)*sizeof(Py_Int32)); new_size*sizeof(Py_Int32));
if (rv == NULL) if (rv == NULL)
goto finally; goto finally;
...@@ -591,10 +609,16 @@ longstoimage(PyObject *self, PyObject *args) ...@@ -591,10 +609,16 @@ longstoimage(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
tablen = ysize * zsize * sizeof(Py_Int32); 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); starttab = (Py_Int32 *)malloc(tablen);
lengthtab = (Py_Int32 *)malloc(tablen); lengthtab = (Py_Int32 *)malloc(tablen);
rlebuflen = (int) (1.05 * xsize + 10);
rlebuf = (unsigned char *)malloc(rlebuflen); rlebuf = (unsigned char *)malloc(rlebuflen);
lumbuf = (unsigned char *)malloc(xsize * sizeof(Py_Int32)); lumbuf = (unsigned char *)malloc(xsize * sizeof(Py_Int32));
if (!starttab || !lengthtab || !rlebuf || !lumbuf) { if (!starttab || !lengthtab || !rlebuf || !lumbuf) {
......
...@@ -578,7 +578,7 @@ strop_expandtabs(PyObject *self, PyObject *args) ...@@ -578,7 +578,7 @@ strop_expandtabs(PyObject *self, PyObject *args)
char* e; char* e;
char* p; char* p;
char* q; char* q;
Py_ssize_t i, j; Py_ssize_t i, j, old_j;
PyObject* out; PyObject* out;
char* string; char* string;
Py_ssize_t stringlen; Py_ssize_t stringlen;
...@@ -595,12 +595,18 @@ strop_expandtabs(PyObject *self, PyObject *args) ...@@ -595,12 +595,18 @@ strop_expandtabs(PyObject *self, PyObject *args)
} }
/* First pass: determine size of output string */ /* 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; e = string + stringlen;
for (p = string; p < e; p++) { for (p = string; p < e; p++) {
if (*p == '\t') if (*p == '\t') {
j += tabsize - (j%tabsize); 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++; j++;
if (*p == '\n') { if (*p == '\n') {
i += j; i += j;
...@@ -609,6 +615,11 @@ strop_expandtabs(PyObject *self, PyObject *args) ...@@ -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 */ /* Second pass: create output string and fill it */
out = PyString_FromStringAndSize(NULL, i+j); out = PyString_FromStringAndSize(NULL, i+j);
if (out == NULL) if (out == NULL)
......
...@@ -207,7 +207,10 @@ PyBuffer_New(Py_ssize_t size) ...@@ -207,7 +207,10 @@ PyBuffer_New(Py_ssize_t size)
"size must be zero or positive"); "size must be zero or positive");
return NULL; return NULL;
} }
/* XXX: check for overflow in multiply */ if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
/* unlikely */
return PyErr_NoMemory();
}
/* Inline PyObject_New */ /* Inline PyObject_New */
o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size); o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
if ( o == NULL ) if ( o == NULL )
...@@ -397,6 +400,8 @@ buffer_concat(PyBufferObject *self, PyObject *other) ...@@ -397,6 +400,8 @@ buffer_concat(PyBufferObject *self, PyObject *other)
if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 ) if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
return NULL; return NULL;
assert(count <= PY_SIZE_MAX - size);
ob = PyString_FromStringAndSize(NULL, size + count); ob = PyString_FromStringAndSize(NULL, size + count);
if ( ob == NULL ) if ( ob == NULL )
return NULL; return NULL;
......
...@@ -45,7 +45,16 @@ list_resize(PyListObject *self, Py_ssize_t newsize) ...@@ -45,7 +45,16 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
* system realloc(). * system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... * 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) if (newsize == 0)
new_allocated = 0; new_allocated = 0;
items = self->ob_item; items = self->ob_item;
...@@ -92,8 +101,9 @@ PyList_New(Py_ssize_t size) ...@@ -92,8 +101,9 @@ PyList_New(Py_ssize_t size)
return NULL; return NULL;
} }
nbytes = size * sizeof(PyObject *); nbytes = size * sizeof(PyObject *);
/* Check for overflow */ /* Check for overflow without an actual overflow,
if (nbytes / sizeof(PyObject *) != (size_t)size) * which can cause compiler to optimise out */
if (size > PY_SIZE_MAX / sizeof(PyObject *))
return PyErr_NoMemory(); return PyErr_NoMemory();
if (num_free_lists) { if (num_free_lists) {
num_free_lists--; num_free_lists--;
...@@ -1372,6 +1382,10 @@ merge_getmem(MergeState *ms, Py_ssize_t need) ...@@ -1372,6 +1382,10 @@ merge_getmem(MergeState *ms, Py_ssize_t need)
* we don't care what's in the block. * we don't care what's in the block.
*/ */
merge_freemem(ms); merge_freemem(ms);
if (need > PY_SSIZE_T_MAX / sizeof(PyObject*)) {
PyErr_NoMemory();
return -1;
}
ms->a = (PyObject **)PyMem_Malloc(need * sizeof(PyObject*)); ms->a = (PyObject **)PyMem_Malloc(need * sizeof(PyObject*));
if (ms->a) { if (ms->a) {
ms->alloced = need; ms->alloced = need;
...@@ -2537,6 +2551,8 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value) ...@@ -2537,6 +2551,8 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
step = -step; step = -step;
} }
assert(slicelength <= PY_SIZE_MAX / sizeof(PyObject*));
garbage = (PyObject**) garbage = (PyObject**)
PyMem_MALLOC(slicelength*sizeof(PyObject*)); PyMem_MALLOC(slicelength*sizeof(PyObject*));
if (!garbage) { if (!garbage) {
......
...@@ -526,9 +526,9 @@ new_arena(void) ...@@ -526,9 +526,9 @@ new_arena(void)
numarenas = maxarenas ? maxarenas << 1 : INITIAL_ARENA_OBJECTS; numarenas = maxarenas ? maxarenas << 1 : INITIAL_ARENA_OBJECTS;
if (numarenas <= maxarenas) if (numarenas <= maxarenas)
return NULL; /* overflow */ return NULL; /* overflow */
nbytes = numarenas * sizeof(*arenas); if (numarenas > PY_SIZE_MAX / sizeof(*arenas))
if (nbytes / sizeof(*arenas) != numarenas)
return NULL; /* overflow */ return NULL; /* overflow */
nbytes = numarenas * sizeof(*arenas);
arenaobj = (struct arena_object *)realloc(arenas, nbytes); arenaobj = (struct arena_object *)realloc(arenas, nbytes);
if (arenaobj == NULL) if (arenaobj == NULL)
return NULL; return NULL;
......
...@@ -91,6 +91,9 @@ PyNode_AddChild(register node *n1, int type, char *str, int lineno, int col_offs ...@@ -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) if (current_capacity < 0 || required_capacity < 0)
return E_OVERFLOW; return E_OVERFLOW;
if (current_capacity < required_capacity) { if (current_capacity < required_capacity) {
if (required_capacity > PY_SIZE_MAX / sizeof(node)) {
return E_NOMEM;
}
n = n1->n_child; n = n1->n_child;
n = (node *) PyObject_REALLOC(n, n = (node *) PyObject_REALLOC(n,
required_capacity * sizeof(node)); required_capacity * sizeof(node));
......
...@@ -5,8 +5,22 @@ asdl_seq * ...@@ -5,8 +5,22 @@ asdl_seq *
asdl_seq_new(int size, PyArena *arena) asdl_seq_new(int size, PyArena *arena)
{ {
asdl_seq *seq = NULL; asdl_seq *seq = NULL;
size_t n = sizeof(asdl_seq) + size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
(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); seq = (asdl_seq *)PyArena_Malloc(arena, n);
if (!seq) { if (!seq) {
...@@ -22,8 +36,22 @@ asdl_int_seq * ...@@ -22,8 +36,22 @@ asdl_int_seq *
asdl_int_seq_new(int size, PyArena *arena) asdl_int_seq_new(int size, PyArena *arena)
{ {
asdl_int_seq *seq = NULL; asdl_int_seq *seq = NULL;
size_t n = sizeof(asdl_seq) + size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
(size ? (sizeof(int) * (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); seq = (asdl_int_seq *)PyArena_Malloc(arena, n);
if (!seq) { if (!seq) {
......
...@@ -3130,6 +3130,9 @@ decode_unicode(const char *s, size_t len, int rawmode, const char *encoding) ...@@ -3130,6 +3130,9 @@ decode_unicode(const char *s, size_t len, int rawmode, const char *encoding)
buf = (char *)s; buf = (char *)s;
u = NULL; u = NULL;
} else { } else {
/* check for integer overflow */
if (len > PY_SIZE_MAX / 4)
return NULL;
/* "\XX" may become "\u005c\uHHLL" (12 bytes) */ /* "\XX" may become "\u005c\uHHLL" (12 bytes) */
u = PyString_FromStringAndSize((char *)NULL, len * 4); u = PyString_FromStringAndSize((char *)NULL, len * 4);
if (u == NULL) if (u == NULL)
......
...@@ -2496,11 +2496,43 @@ filterstring(PyObject *func, PyObject *strobj) ...@@ -2496,11 +2496,43 @@ filterstring(PyObject *func, PyObject *strobj)
PyString_AS_STRING(item)[0]; PyString_AS_STRING(item)[0];
} else { } else {
/* do we need more space? */ /* 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) { if (need > outlen) {
/* overallocate, to avoid reallocations */ /* 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; need = 2*outlen;
}
if (_PyString_Resize(&result, need)) { if (_PyString_Resize(&result, need)) {
Py_DECREF(item); Py_DECREF(item);
return NULL; return NULL;
...@@ -2592,11 +2624,31 @@ filterunicode(PyObject *func, PyObject *strobj) ...@@ -2592,11 +2624,31 @@ filterunicode(PyObject *func, PyObject *strobj)
else { else {
/* do we need more space? */ /* do we need more space? */
Py_ssize_t need = j + reslen + len - i - 1; 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) { if (need > outlen) {
/* overallocate, /* overallocate,
to avoid reallocations */ to avoid reallocations */
if (need < 2 * outlen) if (need < 2 * outlen) {
need = 2 * outlen; if (outlen > PY_SSIZE_T_MAX / 2) {
Py_DECREF(item);
return NULL;
} else {
need = 2 * outlen;
}
}
if (PyUnicode_Resize( if (PyUnicode_Resize(
&result, need) < 0) { &result, need) < 0) {
Py_DECREF(item); Py_DECREF(item);
......
...@@ -225,6 +225,10 @@ _Py_Mangle(PyObject *privateobj, PyObject *ident) ...@@ -225,6 +225,10 @@ _Py_Mangle(PyObject *privateobj, PyObject *ident)
return ident; /* Don't mangle if class is just underscores */ return ident; /* Don't mangle if class is just underscores */
} }
plen = strlen(p); 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); ident = PyString_FromStringAndSize(NULL, 1 + nlen + plen);
if (!ident) if (!ident)
return 0; return 0;
...@@ -620,6 +624,8 @@ markblocks(unsigned char *code, int len) ...@@ -620,6 +624,8 @@ markblocks(unsigned char *code, int len)
unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int)); unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
int i,j, opcode, blockcnt = 0; int i,j, opcode, blockcnt = 0;
assert(len <= PY_SIZE_MAX / sizeof(int));
if (blocks == NULL) { if (blocks == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return NULL;
...@@ -1281,6 +1287,12 @@ compiler_next_instr(struct compiler *c, basicblock *b) ...@@ -1281,6 +1287,12 @@ compiler_next_instr(struct compiler *c, basicblock *b)
size_t oldsize, newsize; size_t oldsize, newsize;
oldsize = b->b_ialloc * sizeof(struct instr); oldsize = b->b_ialloc * sizeof(struct instr);
newsize = oldsize << 1; newsize = oldsize << 1;
if (oldsize > (PY_SIZE_MAX >> 1)) {
PyErr_NoMemory();
return -1;
}
if (newsize == 0) { if (newsize == 0) {
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
...@@ -4091,6 +4103,10 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno) ...@@ -4091,6 +4103,10 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno)
a->a_lnotab = PyString_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); a->a_lnotab = PyString_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
if (!a->a_lnotab) if (!a->a_lnotab)
return 0; return 0;
if (nblocks > PY_SIZE_MAX / sizeof(basicblock *)) {
PyErr_NoMemory();
return 0;
}
a->a_postorder = (basicblock **)PyObject_Malloc( a->a_postorder = (basicblock **)PyObject_Malloc(
sizeof(basicblock *) * nblocks); sizeof(basicblock *) * nblocks);
if (!a->a_postorder) { if (!a->a_postorder) {
...@@ -4199,10 +4215,14 @@ assemble_lnotab(struct assembler *a, struct instr *i) ...@@ -4199,10 +4215,14 @@ assemble_lnotab(struct assembler *a, struct instr *i)
nbytes = a->a_lnotab_off + 2 * ncodes; nbytes = a->a_lnotab_off + 2 * ncodes;
len = PyString_GET_SIZE(a->a_lnotab); len = PyString_GET_SIZE(a->a_lnotab);
if (nbytes >= len) { if (nbytes >= len) {
if (len * 2 < nbytes) if ((len <= INT_MAX / 2) && (len * 2 < nbytes))
len = nbytes; len = nbytes;
else else if (len <= INT_MAX / 2)
len *= 2; len *= 2;
else {
PyErr_NoMemory();
return 0;
}
if (_PyString_Resize(&a->a_lnotab, len) < 0) if (_PyString_Resize(&a->a_lnotab, len) < 0)
return 0; return 0;
} }
...@@ -4221,10 +4241,14 @@ assemble_lnotab(struct assembler *a, struct instr *i) ...@@ -4221,10 +4241,14 @@ assemble_lnotab(struct assembler *a, struct instr *i)
nbytes = a->a_lnotab_off + 2 * ncodes; nbytes = a->a_lnotab_off + 2 * ncodes;
len = PyString_GET_SIZE(a->a_lnotab); len = PyString_GET_SIZE(a->a_lnotab);
if (nbytes >= len) { if (nbytes >= len) {
if (len * 2 < nbytes) if ((len <= INT_MAX / 2) && len * 2 < nbytes)
len = nbytes; len = nbytes;
else else if (len <= INT_MAX / 2)
len *= 2; len *= 2;
else {
PyErr_NoMemory();
return 0;
}
if (_PyString_Resize(&a->a_lnotab, len) < 0) if (_PyString_Resize(&a->a_lnotab, len) < 0)
return 0; return 0;
} }
...@@ -4283,6 +4307,8 @@ assemble_emit(struct assembler *a, struct instr *i) ...@@ -4283,6 +4307,8 @@ assemble_emit(struct assembler *a, struct instr *i)
if (i->i_lineno && !assemble_lnotab(a, i)) if (i->i_lineno && !assemble_lnotab(a, i))
return 0; return 0;
if (a->a_offset + size >= len) { if (a->a_offset + size >= len) {
if (len > PY_SSIZE_T_MAX / 2)
return 0;
if (_PyString_Resize(&a->a_bytecode, len * 2) < 0) if (_PyString_Resize(&a->a_bytecode, len * 2) < 0)
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment