Skip to content

Commit d254ca8

Browse files
committed
Backport of r61180:
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.
1 parent 80bdb48 commit d254ca8

16 files changed

+309
-34
lines changed

Include/pymem.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,18 @@ PyAPI_FUNC(void) PyMem_Free(void *);
8686
*/
8787

8888
#define PyMem_New(type, n) \
89-
( (type *) PyMem_Malloc((n) * sizeof(type)) )
89+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
90+
( (type *) PyMem_Malloc((n) * sizeof(type)) ) )
9091
#define PyMem_NEW(type, n) \
91-
( (type *) PyMem_MALLOC((n) * sizeof(type)) )
92+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
93+
( (type *) PyMem_MALLOC((n) * sizeof(type)) ) )
9294

9395
#define PyMem_Resize(p, type, n) \
94-
( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
96+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
97+
( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) ) )
9598
#define PyMem_RESIZE(p, type, n) \
96-
( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
99+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
100+
( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) ) )
97101

98102
/* In order to avoid breaking old code mixing PyObject_{New, NEW} with
99103
PyMem_{Del, DEL} and PyMem_{Free, FREE}, the PyMem "release memory"

Include/pyport.h

+11
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,17 @@ typedef struct fd_set {
554554
#error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."
555555
#endif
556556

557+
/* Largest possible value of size_t.
558+
SIZE_MAX is part of C99, so it might be defined on some
559+
platforms. If it is not defined, (size_t)-1 is a portable
560+
definition for C89, due to the way signed->unsigned
561+
conversion is defined. */
562+
#ifdef SIZE_MAX
563+
#define PY_SIZE_MAX SIZE_MAX
564+
#else
565+
#define PY_SIZE_MAX ((size_t)-1)
566+
#endif
567+
557568
#ifdef __cplusplus
558569
}
559570
#endif

Misc/NEWS

+13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@ Python News
44

55
(editors: check NEWS.help for information about editing NEWS using ReST.)
66

7+
What's New in Python 2.3.7c1?
8+
===========================
9+
10+
*Release date: 02-Mar-2008*
11+
12+
Core and builtins
13+
-----------------
14+
15+
- Added checks for integer overflows, contributed by Google. Some are
16+
only available if asserts are left in the code, in cases where they
17+
can't be triggered from Python code.
18+
19+
720
What's New in Python 2.3.6?
821
===========================
922

Modules/_csv.c

+10
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ parse_grow_buff(ReaderObj *self)
470470
self->field = PyMem_Malloc(self->field_size);
471471
}
472472
else {
473+
if (self->field_size > INT_MAX / 2) {
474+
PyErr_NoMemory();
475+
return 0;
476+
}
473477
self->field_size *= 2;
474478
self->field = PyMem_Realloc(self->field, self->field_size);
475479
}
@@ -1003,6 +1007,12 @@ join_append_data(WriterObj *self, char *field, int quote_empty,
10031007
static int
10041008
join_check_rec_size(WriterObj *self, int rec_len)
10051009
{
1010+
1011+
if (rec_len < 0 || rec_len > INT_MAX - MEM_INCR) {
1012+
PyErr_NoMemory();
1013+
return 0;
1014+
}
1015+
10061016
if (rec_len > self->rec_size) {
10071017
if (self->rec_size == 0) {
10081018
self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;

Modules/arraymodule.c

+33-1
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,9 @@ array_concat(arrayobject *a, PyObject *bb)
632632
PyErr_BadArgument();
633633
return NULL;
634634
}
635+
if (a->ob_size > INT_MAX - b->ob_size) {
636+
return PyErr_NoMemory();
637+
}
635638
size = a->ob_size + b->ob_size;
636639
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
637640
if (np == NULL) {
@@ -654,6 +657,9 @@ array_repeat(arrayobject *a, int n)
654657
int nbytes;
655658
if (n < 0)
656659
n = 0;
660+
if ((a->ob_size != 0) && (n > INT_MAX / a->ob_size)) {
661+
return PyErr_NoMemory();
662+
}
657663
size = a->ob_size * n;
658664
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
659665
if (np == NULL)
@@ -775,6 +781,11 @@ array_do_extend(arrayobject *self, PyObject *bb)
775781
"can only extend with array of same kind");
776782
return -1;
777783
}
784+
if ((self->ob_size > INT_MAX - b->ob_size) ||
785+
((self->ob_size + b->ob_size) > INT_MAX / self->ob_descr->itemsize)) {
786+
PyErr_NoMemory();
787+
return -1;
788+
}
778789
size = self->ob_size + b->ob_size;
779790
PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
780791
if (self->ob_item == NULL) {
@@ -809,13 +820,20 @@ array_inplace_repeat(arrayobject *self, int n)
809820
if (n < 0)
810821
n = 0;
811822
items = self->ob_item;
823+
if ((self->ob_descr->itemsize != 0) &&
824+
(self->ob_size > INT_MAX / self->ob_descr->itemsize)) {
825+
return PyErr_NoMemory();
826+
}
812827
size = self->ob_size * self->ob_descr->itemsize;
813828
if (n == 0) {
814829
PyMem_FREE(items);
815830
self->ob_item = NULL;
816831
self->ob_size = 0;
817832
}
818833
else {
834+
if (size > INT_MAX / n) {
835+
return PyErr_NoMemory();
836+
}
819837
PyMem_Resize(items, char, n * size);
820838
if (items == NULL)
821839
return PyErr_NoMemory();
@@ -1224,6 +1242,9 @@ array_fromlist(arrayobject *self, PyObject *list)
12241242
if ((*self->ob_descr->setitem)(self,
12251243
self->ob_size - n + i, v) != 0) {
12261244
self->ob_size -= n;
1245+
if (itemsize && (self->ob_size > INT_MAX / itemsize)) {
1246+
return PyErr_NoMemory();
1247+
}
12271248
PyMem_RESIZE(item, char,
12281249
self->ob_size * itemsize);
12291250
self->ob_item = item;
@@ -1282,6 +1303,10 @@ array_fromstring(arrayobject *self, PyObject *args)
12821303
n = n / itemsize;
12831304
if (n > 0) {
12841305
char *item = self->ob_item;
1306+
if ((n > INT_MAX - self->ob_size) ||
1307+
((self->ob_size + n) > INT_MAX / itemsize)) {
1308+
return PyErr_NoMemory();
1309+
}
12851310
PyMem_RESIZE(item, char, (self->ob_size + n) * itemsize);
12861311
if (item == NULL) {
12871312
PyErr_NoMemory();
@@ -1306,8 +1331,12 @@ values,as if it had been read from a file using the fromfile() method).");
13061331
static PyObject *
13071332
array_tostring(arrayobject *self, PyObject *unused)
13081333
{
1309-
return PyString_FromStringAndSize(self->ob_item,
1334+
if (self->ob_size <= INT_MAX / self->ob_descr->itemsize) {
1335+
return PyString_FromStringAndSize(self->ob_item,
13101336
self->ob_size * self->ob_descr->itemsize);
1337+
} else {
1338+
return PyErr_NoMemory();
1339+
}
13111340
}
13121341

13131342
PyDoc_STRVAR(tostring_doc,
@@ -1335,6 +1364,9 @@ array_fromunicode(arrayobject *self, PyObject *args)
13351364
}
13361365
if (n > 0) {
13371366
Py_UNICODE *item = (Py_UNICODE *) self->ob_item;
1367+
if (self->ob_size > INT_MAX - n) {
1368+
return PyErr_NoMemory();
1369+
}
13381370
PyMem_RESIZE(item, Py_UNICODE, self->ob_size + n);
13391371
if (item == NULL) {
13401372
PyErr_NoMemory();

Modules/audioop.c

+44-12
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ static PyObject *
674674
audioop_tostereo(PyObject *self, PyObject *args)
675675
{
676676
signed char *cp, *ncp;
677-
int len, size, val1, val2, val = 0;
677+
int len, new_len, size, val1, val2, val = 0;
678678
double fac1, fac2, fval, maxval;
679679
PyObject *rv;
680680
int i;
@@ -690,7 +690,14 @@ audioop_tostereo(PyObject *self, PyObject *args)
690690
return 0;
691691
}
692692

693-
rv = PyString_FromStringAndSize(NULL, len*2);
693+
new_len = len*2;
694+
if (new_len < 0) {
695+
PyErr_SetString(PyExc_MemoryError,
696+
"not enough memory for output buffer");
697+
return 0;
698+
}
699+
700+
rv = PyString_FromStringAndSize(NULL, new_len);
694701
if ( rv == 0 )
695702
return 0;
696703
ncp = (signed char *)PyString_AsString(rv);
@@ -853,7 +860,7 @@ audioop_lin2lin(PyObject *self, PyObject *args)
853860
{
854861
signed char *cp;
855862
unsigned char *ncp;
856-
int len, size, size2, val = 0;
863+
int len, new_len, size, size2, val = 0;
857864
PyObject *rv;
858865
int i, j;
859866

@@ -867,7 +874,13 @@ audioop_lin2lin(PyObject *self, PyObject *args)
867874
return 0;
868875
}
869876

870-
rv = PyString_FromStringAndSize(NULL, (len/size)*size2);
877+
new_len = (len/size)*size2;
878+
if (new_len < 0) {
879+
PyErr_SetString(PyExc_MemoryError,
880+
"not enough memory for output buffer");
881+
return 0;
882+
}
883+
rv = PyString_FromStringAndSize(NULL, new_len);
871884
if ( rv == 0 )
872885
return 0;
873886
ncp = (unsigned char *)PyString_AsString(rv);
@@ -903,6 +916,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
903916
int chan, d, *prev_i, *cur_i, cur_o;
904917
PyObject *state, *samps, *str, *rv = NULL;
905918
int bytes_per_frame;
919+
size_t alloc_size;
906920

907921
weightA = 1;
908922
weightB = 0;
@@ -944,8 +958,14 @@ audioop_ratecv(PyObject *self, PyObject *args)
944958
inrate /= d;
945959
outrate /= d;
946960

947-
prev_i = (int *) malloc(nchannels * sizeof(int));
948-
cur_i = (int *) malloc(nchannels * sizeof(int));
961+
alloc_size = sizeof(int) * (unsigned)nchannels;
962+
if (alloc_size < nchannels) {
963+
PyErr_SetString(PyExc_MemoryError,
964+
"not enough memory for output buffer");
965+
return 0;
966+
}
967+
prev_i = (int *) malloc(alloc_size);
968+
cur_i = (int *) malloc(alloc_size);
949969
if (prev_i == NULL || cur_i == NULL) {
950970
(void) PyErr_NoMemory();
951971
goto exit;
@@ -1114,7 +1134,7 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
11141134
unsigned char *cp;
11151135
unsigned char cval;
11161136
signed char *ncp;
1117-
int len, size, val;
1137+
int len, new_len, size, val;
11181138
PyObject *rv;
11191139
int i;
11201140

@@ -1127,12 +1147,18 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
11271147
return 0;
11281148
}
11291149

1130-
rv = PyString_FromStringAndSize(NULL, len*size);
1150+
new_len = len*size;
1151+
if (new_len < 0) {
1152+
PyErr_SetString(PyExc_MemoryError,
1153+
"not enough memory for output buffer");
1154+
return 0;
1155+
}
1156+
rv = PyString_FromStringAndSize(NULL, new_len);
11311157
if ( rv == 0 )
11321158
return 0;
11331159
ncp = (signed char *)PyString_AsString(rv);
11341160

1135-
for ( i=0; i < len*size; i += size ) {
1161+
for ( i=0; i < new_len; i += size ) {
11361162
cval = *cp++;
11371163
val = st_ulaw_to_linear(cval);
11381164

@@ -1257,7 +1283,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
12571283
{
12581284
signed char *cp;
12591285
signed char *ncp;
1260-
int len, size, valpred, step, delta, index, sign, vpdiff;
1286+
int len, new_len, size, valpred, step, delta, index, sign, vpdiff;
12611287
PyObject *rv, *str, *state;
12621288
int i, inputbuffer = 0, bufferstep;
12631289

@@ -1279,15 +1305,21 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
12791305
} else if ( !PyArg_Parse(state, "(ii)", &valpred, &index) )
12801306
return 0;
12811307

1282-
str = PyString_FromStringAndSize(NULL, len*size*2);
1308+
new_len = len*size*2;
1309+
if (new_len < 0) {
1310+
PyErr_SetString(PyExc_MemoryError,
1311+
"not enough memory for output buffer");
1312+
return 0;
1313+
}
1314+
str = PyString_FromStringAndSize(NULL, new_len);
12831315
if ( str == 0 )
12841316
return 0;
12851317
ncp = (signed char *)PyString_AsString(str);
12861318

12871319
step = stepsizeTable[index];
12881320
bufferstep = 0;
12891321

1290-
for ( i=0; i < len*size*2; i += size ) {
1322+
for ( i=0; i < new_len; i += size ) {
12911323
/* Step 1 - get the delta value and compute next index */
12921324
if ( bufferstep ) {
12931325
delta = inputbuffer & 0xf;

0 commit comments

Comments
 (0)