Skip to content

Commit 534cb6a

Browse files
author
amaury.forgeotdarc
committed
Merged revisions 64114 via svnmerge from
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. ........ git-svn-id: http://svn.python.org/projects/python/branches/py3k@64364 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 370cb9f commit 534cb6a

16 files changed

Lines changed: 299 additions & 44 deletions

File tree

Include/pymem.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,18 @@ PyAPI_FUNC(void) PyMem_Free(void *);
8585
*/
8686

8787
#define PyMem_New(type, n) \
88-
( (type *) PyMem_Malloc((n) * sizeof(type)) )
88+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
89+
( (type *) PyMem_Malloc((n) * sizeof(type)) ) )
8990
#define PyMem_NEW(type, n) \
90-
( (type *) PyMem_MALLOC((n) * sizeof(type)) )
91+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
92+
( (type *) PyMem_MALLOC((n) * sizeof(type)) ) )
9193

9294
#define PyMem_Resize(p, type, n) \
93-
( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
95+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
96+
( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) ) )
9497
#define PyMem_RESIZE(p, type, n) \
95-
( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
98+
( assert((n) <= PY_SIZE_MAX / sizeof(type)) , \
99+
( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) ) )
96100

97101
/* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used
98102
* anymore. They're just confusing aliases for PyMem_{Free,FREE} now.

Include/pyport.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,17 @@ typedef Py_intptr_t Py_ssize_t;
106106
# error "Python needs a typedef for Py_ssize_t in pyport.h."
107107
#endif
108108

109+
/* Largest possible value of size_t.
110+
SIZE_MAX is part of C99, so it might be defined on some
111+
platforms. If it is not defined, (size_t)-1 is a portable
112+
definition for C89, due to the way signed->unsigned
113+
conversion is defined. */
114+
#ifdef SIZE_MAX
115+
#define PY_SIZE_MAX SIZE_MAX
116+
#else
117+
#define PY_SIZE_MAX ((size_t)-1)
118+
#endif
119+
109120
/* Largest positive value of type Py_ssize_t. */
110121
#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))
111122
/* Smallest negative value of type Py_ssize_t. */

Lib/test/test_array.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,23 @@ class FloatTest(FPTest):
962962
class DoubleTest(FPTest):
963963
typecode = 'd'
964964
minitemsize = 8
965+
966+
def test_alloc_overflow(self):
967+
a = array.array('d', [-1]*65536)
968+
try:
969+
a *= 65536
970+
except MemoryError:
971+
pass
972+
else:
973+
self.fail("a *= 2**16 didn't raise MemoryError")
974+
b = array.array('d', [ 2.71828183, 3.14159265, -1])
975+
try:
976+
b * 1431655766
977+
except MemoryError:
978+
pass
979+
else:
980+
self.fail("a * 1431655766 didn't raise MemoryError")
981+
965982
tests.append(DoubleTest)
966983

967984
def test_main(verbose=None):

Modules/_csv.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,10 @@ parse_grow_buff(ReaderObj *self)
533533
self->field = PyMem_New(Py_UNICODE, self->field_size);
534534
}
535535
else {
536+
if (self->field_size > INT_MAX / 2) {
537+
PyErr_NoMemory();
538+
return 0;
539+
}
536540
self->field_size *= 2;
537541
self->field = PyMem_Resize(self->field, Py_UNICODE,
538542
self->field_size);
@@ -1038,6 +1042,12 @@ join_append_data(WriterObj *self, Py_UNICODE *field, int quote_empty,
10381042
static int
10391043
join_check_rec_size(WriterObj *self, int rec_len)
10401044
{
1045+
1046+
if (rec_len < 0 || rec_len > INT_MAX - MEM_INCR) {
1047+
PyErr_NoMemory();
1048+
return 0;
1049+
}
1050+
10411051
if (rec_len > self->rec_size) {
10421052
if (self->rec_size == 0) {
10431053
self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;

Modules/arraymodule.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,9 @@ array_concat(arrayobject *a, PyObject *bb)
642642
PyErr_BadArgument();
643643
return NULL;
644644
}
645+
if (Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b)) {
646+
return PyErr_NoMemory();
647+
}
645648
size = Py_SIZE(a) + Py_SIZE(b);
646649
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
647650
if (np == NULL) {
@@ -664,6 +667,9 @@ array_repeat(arrayobject *a, Py_ssize_t n)
664667
Py_ssize_t nbytes;
665668
if (n < 0)
666669
n = 0;
670+
if ((Py_SIZE(a) != 0) && (n > PY_SSIZE_T_MAX / Py_SIZE(a))) {
671+
return PyErr_NoMemory();
672+
}
667673
size = Py_SIZE(a) * n;
668674
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
669675
if (np == NULL)
@@ -853,6 +859,10 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
853859
if (n < 0)
854860
n = 0;
855861
items = self->ob_item;
862+
if ((self->ob_descr->itemsize != 0) &&
863+
(Py_SIZE(self) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
864+
return PyErr_NoMemory();
865+
}
856866
size = Py_SIZE(self) * self->ob_descr->itemsize;
857867
if (n == 0) {
858868
PyMem_FREE(items);
@@ -861,6 +871,9 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
861871
self->allocated = 0;
862872
}
863873
else {
874+
if (size > PY_SSIZE_T_MAX / n) {
875+
return PyErr_NoMemory();
876+
}
864877
PyMem_Resize(items, char, n * size);
865878
if (items == NULL)
866879
return PyErr_NoMemory();
@@ -1142,6 +1155,10 @@ array_reduce(arrayobject *array)
11421155
Py_INCREF(dict);
11431156
}
11441157
if (Py_SIZE(array) > 0) {
1158+
if (array->ob_descr->itemsize
1159+
> PY_SSIZE_T_MAX / Py_SIZE(array)) {
1160+
return PyErr_NoMemory();
1161+
}
11451162
result = Py_BuildValue("O(cy#)O",
11461163
Py_TYPE(array),
11471164
array->ob_descr->typecode,
@@ -1315,6 +1332,9 @@ array_fromlist(arrayobject *self, PyObject *list)
13151332
if ((*self->ob_descr->setitem)(self,
13161333
Py_SIZE(self) - n + i, v) != 0) {
13171334
Py_SIZE(self) -= n;
1335+
if (itemsize && (Py_SIZE(self) > PY_SSIZE_T_MAX / itemsize)) {
1336+
return PyErr_NoMemory();
1337+
}
13181338
PyMem_RESIZE(item, char,
13191339
Py_SIZE(self) * itemsize);
13201340
self->ob_item = item;
@@ -1373,6 +1393,10 @@ array_fromstring(arrayobject *self, PyObject *args)
13731393
n = n / itemsize;
13741394
if (n > 0) {
13751395
char *item = self->ob_item;
1396+
if ((n > PY_SSIZE_T_MAX - Py_SIZE(self)) ||
1397+
((Py_SIZE(self) + n) > PY_SSIZE_T_MAX / itemsize)) {
1398+
return PyErr_NoMemory();
1399+
}
13761400
PyMem_RESIZE(item, char, (Py_SIZE(self) + n) * itemsize);
13771401
if (item == NULL) {
13781402
PyErr_NoMemory();
@@ -1398,8 +1422,12 @@ values, as if it had been read from a file using the fromfile() method).");
13981422
static PyObject *
13991423
array_tostring(arrayobject *self, PyObject *unused)
14001424
{
1401-
return PyBytes_FromStringAndSize(self->ob_item,
1402-
Py_SIZE(self) * self->ob_descr->itemsize);
1425+
if (Py_SIZE(self) <= PY_SSIZE_T_MAX / self->ob_descr->itemsize) {
1426+
return PyBytes_FromStringAndSize(self->ob_item,
1427+
Py_SIZE(self) * self->ob_descr->itemsize);
1428+
} else {
1429+
return PyErr_NoMemory();
1430+
}
14031431
}
14041432

14051433
PyDoc_STRVAR(tostring_doc,
@@ -1428,6 +1456,9 @@ array_fromunicode(arrayobject *self, PyObject *args)
14281456
}
14291457
if (n > 0) {
14301458
Py_UNICODE *item = (Py_UNICODE *) self->ob_item;
1459+
if (Py_SIZE(self) > PY_SSIZE_T_MAX - n) {
1460+
return PyErr_NoMemory();
1461+
}
14311462
PyMem_RESIZE(item, Py_UNICODE, Py_SIZE(self) + n);
14321463
if (item == NULL) {
14331464
PyErr_NoMemory();

Modules/audioop.c

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ static PyObject *
829829
audioop_tostereo(PyObject *self, PyObject *args)
830830
{
831831
signed char *cp, *ncp;
832-
int len, size, val1, val2, val = 0;
832+
int len, new_len, size, val1, val2, val = 0;
833833
double fac1, fac2, fval, maxval;
834834
PyObject *rv;
835835
int i;
@@ -846,7 +846,14 @@ audioop_tostereo(PyObject *self, PyObject *args)
846846
return 0;
847847
}
848848

849-
rv = PyBytes_FromStringAndSize(NULL, len*2);
849+
new_len = len*2;
850+
if (new_len < 0) {
851+
PyErr_SetString(PyExc_MemoryError,
852+
"not enough memory for output buffer");
853+
return 0;
854+
}
855+
856+
rv = PyBytes_FromStringAndSize(NULL, new_len);
850857
if ( rv == 0 )
851858
return 0;
852859
ncp = (signed char *)PyBytes_AsString(rv);
@@ -1009,7 +1016,7 @@ audioop_lin2lin(PyObject *self, PyObject *args)
10091016
{
10101017
signed char *cp;
10111018
unsigned char *ncp;
1012-
int len, size, size2, val = 0;
1019+
int len, new_len, size, size2, val = 0;
10131020
PyObject *rv;
10141021
int i, j;
10151022

@@ -1023,7 +1030,13 @@ audioop_lin2lin(PyObject *self, PyObject *args)
10231030
return 0;
10241031
}
10251032

1026-
rv = PyBytes_FromStringAndSize(NULL, (len/size)*size2);
1033+
new_len = (len/size)*size2;
1034+
if (new_len < 0) {
1035+
PyErr_SetString(PyExc_MemoryError,
1036+
"not enough memory for output buffer");
1037+
return 0;
1038+
}
1039+
rv = PyBytes_FromStringAndSize(NULL, new_len);
10271040
if ( rv == 0 )
10281041
return 0;
10291042
ncp = (unsigned char *)PyBytes_AsString(rv);
@@ -1059,6 +1072,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
10591072
int chan, d, *prev_i, *cur_i, cur_o;
10601073
PyObject *state, *samps, *str, *rv = NULL;
10611074
int bytes_per_frame;
1075+
size_t alloc_size;
10621076

10631077
weightA = 1;
10641078
weightB = 0;
@@ -1101,8 +1115,14 @@ audioop_ratecv(PyObject *self, PyObject *args)
11011115
inrate /= d;
11021116
outrate /= d;
11031117

1104-
prev_i = (int *) malloc(nchannels * sizeof(int));
1105-
cur_i = (int *) malloc(nchannels * sizeof(int));
1118+
alloc_size = sizeof(int) * (unsigned)nchannels;
1119+
if (alloc_size < nchannels) {
1120+
PyErr_SetString(PyExc_MemoryError,
1121+
"not enough memory for output buffer");
1122+
return 0;
1123+
}
1124+
prev_i = (int *) malloc(alloc_size);
1125+
cur_i = (int *) malloc(alloc_size);
11061126
if (prev_i == NULL || cur_i == NULL) {
11071127
(void) PyErr_NoMemory();
11081128
goto exit;
@@ -1275,7 +1295,7 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
12751295
unsigned char *cp;
12761296
unsigned char cval;
12771297
signed char *ncp;
1278-
int len, size, val;
1298+
int len, new_len, size, val;
12791299
PyObject *rv;
12801300
int i;
12811301

@@ -1288,12 +1308,18 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
12881308
return 0;
12891309
}
12901310

1291-
rv = PyBytes_FromStringAndSize(NULL, len*size);
1311+
new_len = len*size;
1312+
if (new_len < 0) {
1313+
PyErr_SetString(PyExc_MemoryError,
1314+
"not enough memory for output buffer");
1315+
return 0;
1316+
}
1317+
rv = PyBytes_FromStringAndSize(NULL, new_len);
12921318
if ( rv == 0 )
12931319
return 0;
12941320
ncp = (signed char *)PyBytes_AsString(rv);
12951321

1296-
for ( i=0; i < len*size; i += size ) {
1322+
for ( i=0; i < new_len; i += size ) {
12971323
cval = *cp++;
12981324
val = st_ulaw2linear16(cval);
12991325

@@ -1343,7 +1369,7 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
13431369
unsigned char *cp;
13441370
unsigned char cval;
13451371
signed char *ncp;
1346-
int len, size, val;
1372+
int len, new_len, size, val;
13471373
PyObject *rv;
13481374
int i;
13491375

@@ -1356,12 +1382,18 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
13561382
return 0;
13571383
}
13581384

1359-
rv = PyBytes_FromStringAndSize(NULL, len*size);
1385+
new_len = len*size;
1386+
if (new_len < 0) {
1387+
PyErr_SetString(PyExc_MemoryError,
1388+
"not enough memory for output buffer");
1389+
return 0;
1390+
}
1391+
rv = PyBytes_FromStringAndSize(NULL, new_len);
13601392
if ( rv == 0 )
13611393
return 0;
13621394
ncp = (signed char *)PyBytes_AsString(rv);
13631395

1364-
for ( i=0; i < len*size; i += size ) {
1396+
for ( i=0; i < new_len; i += size ) {
13651397
cval = *cp++;
13661398
val = st_alaw2linear16(cval);
13671399

@@ -1486,7 +1518,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
14861518
{
14871519
signed char *cp;
14881520
signed char *ncp;
1489-
int len, size, valpred, step, delta, index, sign, vpdiff;
1521+
int len, new_len, size, valpred, step, delta, index, sign, vpdiff;
14901522
PyObject *rv, *str, *state;
14911523
int i, inputbuffer = 0, bufferstep;
14921524

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

1511-
str = PyBytes_FromStringAndSize(NULL, len*size*2);
1543+
new_len = len*size*2;
1544+
if (new_len < 0) {
1545+
PyErr_SetString(PyExc_MemoryError,
1546+
"not enough memory for output buffer");
1547+
return 0;
1548+
}
1549+
str = PyBytes_FromStringAndSize(NULL, new_len);
15121550
if ( str == 0 )
15131551
return 0;
15141552
ncp = (signed char *)PyBytes_AsString(str);
15151553

15161554
step = stepsizeTable[index];
15171555
bufferstep = 0;
15181556

1519-
for ( i=0; i < len*size*2; i += size ) {
1557+
for ( i=0; i < new_len; i += size ) {
15201558
/* Step 1 - get the delta value and compute next index */
15211559
if ( bufferstep ) {
15221560
delta = inputbuffer & 0xf;

0 commit comments

Comments
 (0)