Skip to content

Commit

Permalink
Merged revisions 64114 via svnmerge from
Browse files Browse the repository at this point in the history
svn+ssh://[email protected]/python/trunk

........
  r64114 | gregory.p.smith | 2008-06-11 09:41:16 +0200 (mer., 11 juin 2008) | 6 lines

  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.
........
  • Loading branch information
amauryfa committed Jun 18, 2008
1 parent 036aa54 commit 9c74b14
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 44 deletions.
12 changes: 8 additions & 4 deletions Include/pymem.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,18 @@ PyAPI_FUNC(void) PyMem_Free(void *);
*/

#define PyMem_New(type, n) \
( (type *) PyMem_Malloc((n) * sizeof(type)) )
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
( (type *) PyMem_Malloc((n) * sizeof(type)) ) )
#define PyMem_NEW(type, n) \
( (type *) PyMem_MALLOC((n) * sizeof(type)) )
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
( (type *) PyMem_MALLOC((n) * sizeof(type)) ) )

#define PyMem_Resize(p, type, n) \
( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) ) )
#define PyMem_RESIZE(p, type, n) \
( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) ) )

/* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used
* anymore. They're just confusing aliases for PyMem_{Free,FREE} now.
Expand Down
11 changes: 11 additions & 0 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ typedef Py_intptr_t Py_ssize_t;
# error "Python needs a typedef for Py_ssize_t in pyport.h."
#endif

/* Largest possible value of size_t.
SIZE_MAX is part of C99, so it might be defined on some
platforms. If it is not defined, (size_t)-1 is a portable
definition for C89, due to the way signed->unsigned
conversion is defined. */
#ifdef SIZE_MAX
#define PY_SIZE_MAX SIZE_MAX
#else
#define PY_SIZE_MAX ((size_t)-1)
#endif

/* Largest positive value of type Py_ssize_t. */
#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))
/* Smallest negative value of type Py_ssize_t. */
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,23 @@ class FloatTest(FPTest):
class DoubleTest(FPTest):
typecode = 'd'
minitemsize = 8

def test_alloc_overflow(self):
a = array.array('d', [-1]*65536)
try:
a *= 65536
except MemoryError:
pass
else:
self.fail("a *= 2**16 didn't raise MemoryError")
b = array.array('d', [ 2.71828183, 3.14159265, -1])
try:
b * 1431655766
except MemoryError:
pass
else:
self.fail("a * 1431655766 didn't raise MemoryError")

tests.append(DoubleTest)

def test_main(verbose=None):
Expand Down
10 changes: 10 additions & 0 deletions Modules/_csv.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,10 @@ parse_grow_buff(ReaderObj *self)
self->field = PyMem_New(Py_UNICODE, self->field_size);
}
else {
if (self->field_size > INT_MAX / 2) {
PyErr_NoMemory();
return 0;
}
self->field_size *= 2;
self->field = PyMem_Resize(self->field, Py_UNICODE,
self->field_size);
Expand Down Expand Up @@ -1038,6 +1042,12 @@ join_append_data(WriterObj *self, Py_UNICODE *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;
Expand Down
35 changes: 33 additions & 2 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,9 @@ array_concat(arrayobject *a, PyObject *bb)
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) {
Expand All @@ -664,6 +667,9 @@ array_repeat(arrayobject *a, Py_ssize_t n)
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)
Expand Down Expand Up @@ -853,6 +859,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) &&
(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);
Expand All @@ -861,6 +871,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();
Expand Down Expand Up @@ -1142,6 +1155,10 @@ array_reduce(arrayobject *array)
Py_INCREF(dict);
}
if (Py_SIZE(array) > 0) {
if (array->ob_descr->itemsize
> PY_SSIZE_T_MAX / Py_SIZE(array)) {
return PyErr_NoMemory();
}
result = Py_BuildValue("O(cy#)O",
Py_TYPE(array),
array->ob_descr->typecode,
Expand Down Expand Up @@ -1315,6 +1332,9 @@ array_fromlist(arrayobject *self, PyObject *list)
if ((*self->ob_descr->setitem)(self,
Py_SIZE(self) - n + i, v) != 0) {
Py_SIZE(self) -= n;
if (itemsize && (Py_SIZE(self) > PY_SSIZE_T_MAX / itemsize)) {
return PyErr_NoMemory();
}
PyMem_RESIZE(item, char,
Py_SIZE(self) * itemsize);
self->ob_item = item;
Expand Down Expand Up @@ -1373,6 +1393,10 @@ array_fromstring(arrayobject *self, PyObject *args)
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();
Expand All @@ -1398,8 +1422,12 @@ values, as if it had been read from a file using the fromfile() method).");
static PyObject *
array_tostring(arrayobject *self, PyObject *unused)
{
return PyBytes_FromStringAndSize(self->ob_item,
Py_SIZE(self) * self->ob_descr->itemsize);
if (Py_SIZE(self) <= PY_SSIZE_T_MAX / self->ob_descr->itemsize) {
return PyBytes_FromStringAndSize(self->ob_item,
Py_SIZE(self) * self->ob_descr->itemsize);
} else {
return PyErr_NoMemory();
}
}

PyDoc_STRVAR(tostring_doc,
Expand Down Expand Up @@ -1428,6 +1456,9 @@ array_fromunicode(arrayobject *self, PyObject *args)
}
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();
Expand Down
68 changes: 53 additions & 15 deletions Modules/audioop.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,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;
Expand All @@ -846,7 +846,14 @@ audioop_tostereo(PyObject *self, PyObject *args)
return 0;
}

rv = PyBytes_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 = PyBytes_FromStringAndSize(NULL, new_len);
if ( rv == 0 )
return 0;
ncp = (signed char *)PyBytes_AsString(rv);
Expand Down Expand Up @@ -1009,7 +1016,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;

Expand All @@ -1023,7 +1030,13 @@ audioop_lin2lin(PyObject *self, PyObject *args)
return 0;
}

rv = PyBytes_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 = PyBytes_FromStringAndSize(NULL, new_len);
if ( rv == 0 )
return 0;
ncp = (unsigned char *)PyBytes_AsString(rv);
Expand Down Expand Up @@ -1059,6 +1072,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;
Expand Down Expand Up @@ -1101,8 +1115,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;
Expand Down Expand Up @@ -1275,7 +1295,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;

Expand All @@ -1288,12 +1308,18 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
return 0;
}

rv = PyBytes_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 = PyBytes_FromStringAndSize(NULL, new_len);
if ( rv == 0 )
return 0;
ncp = (signed char *)PyBytes_AsString(rv);

for ( i=0; i < len*size; i += size ) {
for ( i=0; i < new_len; i += size ) {
cval = *cp++;
val = st_ulaw2linear16(cval);

Expand Down Expand Up @@ -1343,7 +1369,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;

Expand All @@ -1356,12 +1382,18 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
return 0;
}

rv = PyBytes_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 = PyBytes_FromStringAndSize(NULL, new_len);
if ( rv == 0 )
return 0;
ncp = (signed char *)PyBytes_AsString(rv);

for ( i=0; i < len*size; i += size ) {
for ( i=0; i < new_len; i += size ) {
cval = *cp++;
val = st_alaw2linear16(cval);

Expand Down Expand Up @@ -1486,7 +1518,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;

Expand All @@ -1508,15 +1540,21 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
} else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) )
return 0;

str = PyBytes_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 = PyBytes_FromStringAndSize(NULL, new_len);
if ( str == 0 )
return 0;
ncp = (signed char *)PyBytes_AsString(str);

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;
Expand Down
Loading

0 comments on commit 9c74b14

Please sign in to comment.