Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9c74b14

Browse files
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. ........
1 parent 036aa54 commit 9c74b14

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)