Skip to content

Commit b93d7d5

Browse files
committed
Security patches from Apple: prevent int overflow when allocating memory
1 parent 46b3a79 commit b93d7d5

File tree

8 files changed

+87
-15
lines changed

8 files changed

+87
-15
lines changed

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ What's New in Python 2.4.5c1?
1818
Core and builtins
1919
-----------------
2020

21+
- Apply security patches from Apple.
22+
2123
- Issue #2620: Overflow checking when allocating or reallocating memory
2224
was not always being done properly in some python types and extension
2325
modules. PyMem_MALLOC, PyMem_REALLOC, PyMem_NEW and PyMem_RESIZE have

Modules/gcmodule.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,10 @@ PyObject *
12491249
_PyObject_GC_Malloc(size_t basicsize)
12501250
{
12511251
PyObject *op;
1252-
PyGC_Head *g = PyObject_MALLOC(sizeof(PyGC_Head) + basicsize);
1252+
PyGC_Head *g;
1253+
if (basicsize > INT_MAX - sizeof(PyGC_Head))
1254+
return PyErr_NoMemory();
1255+
g = PyObject_MALLOC(sizeof(PyGC_Head) + basicsize);
12531256
if (g == NULL)
12541257
return PyErr_NoMemory();
12551258
g->gc.gc_refs = GC_UNTRACKED;
@@ -1291,6 +1294,8 @@ _PyObject_GC_Resize(PyVarObject *op, int nitems)
12911294
{
12921295
const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems);
12931296
PyGC_Head *g = AS_GC(op);
1297+
if (basicsize > INT_MAX - sizeof(PyGC_Head))
1298+
return (PyVarObject *)PyErr_NoMemory();
12941299
g = PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize);
12951300
if (g == NULL)
12961301
return (PyVarObject *)PyErr_NoMemory();

Modules/mmapmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ mmap_read_method(mmap_object *self,
223223
return(NULL);
224224

225225
/* silently 'adjust' out-of-range requests */
226-
if ((self->pos + num_bytes) > self->size) {
226+
if (num_bytes > self->size - self->pos) {
227227
num_bytes -= (self->pos+num_bytes) - self->size;
228228
}
229229
result = Py_BuildValue("s#", self->data+self->pos, num_bytes);

Modules/stropmodule.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ strop_joinfields(PyObject *self, PyObject *args)
214214
return NULL;
215215
}
216216
slen = PyString_GET_SIZE(item);
217+
if (slen > INT_MAX - reslen ||
218+
seplen > INT_MAX - reslen - seplen) {
219+
PyErr_SetString(PyExc_OverflowError,
220+
"input too long");
221+
Py_DECREF(res);
222+
return NULL;
223+
}
217224
while (reslen + slen + seplen >= sz) {
218225
if (_PyString_Resize(&res, sz * 2) < 0)
219226
return NULL;
@@ -251,6 +258,14 @@ strop_joinfields(PyObject *self, PyObject *args)
251258
return NULL;
252259
}
253260
slen = PyString_GET_SIZE(item);
261+
if (slen > INT_MAX - reslen ||
262+
seplen > INT_MAX - reslen - seplen) {
263+
PyErr_SetString(PyExc_OverflowError,
264+
"input too long");
265+
Py_DECREF(res);
266+
Py_XDECREF(item);
267+
return NULL;
268+
}
254269
while (reslen + slen + seplen >= sz) {
255270
if (_PyString_Resize(&res, sz * 2) < 0) {
256271
Py_DECREF(item);

Objects/bufferobject.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ buffer_repeat(PyBufferObject *self, int count)
384384
count = 0;
385385
if (!get_buf(self, &ptr, &size))
386386
return NULL;
387+
if (count > INT_MAX / size) {
388+
PyErr_SetString(PyExc_MemoryError, "result too large");
389+
return NULL;
390+
}
387391
ob = PyString_FromStringAndSize(NULL, size * count);
388392
if ( ob == NULL )
389393
return NULL;

Objects/stringobject.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ PyString_FromStringAndSize(const char *str, int size)
6969
return (PyObject *)op;
7070
}
7171

72+
if (size > INT_MAX - sizeof(PyStringObject)) {
73+
PyErr_SetString(PyExc_OverflowError, "string is too large");
74+
return NULL;
75+
}
76+
7277
/* Inline PyObject_NewVar */
7378
op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
7479
if (op == NULL)
@@ -104,7 +109,7 @@ PyString_FromString(const char *str)
104109

105110
assert(str != NULL);
106111
size = strlen(str);
107-
if (size > INT_MAX) {
112+
if (size > INT_MAX - sizeof(PyStringObject)) {
108113
PyErr_SetString(PyExc_OverflowError,
109114
"string is too long for a Python string");
110115
return NULL;
@@ -907,7 +912,18 @@ string_concat(register PyStringObject *a, register PyObject *bb)
907912
Py_INCREF(a);
908913
return (PyObject *)a;
909914
}
915+
/* Check that string sizes are not negative, to prevent an
916+
overflow in cases where we are passed incorrectly-created
917+
strings with negative lengths (due to a bug in other code).
918+
*/
910919
size = a->ob_size + b->ob_size;
920+
if (a->ob_size < 0 || b->ob_size < 0 ||
921+
a->ob_size > INT_MAX - b->ob_size) {
922+
PyErr_SetString(PyExc_OverflowError,
923+
"strings are too large to concat");
924+
return NULL;
925+
}
926+
911927
/* Inline PyObject_NewVar */
912928
op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
913929
if (op == NULL)

Objects/tupleobject.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,12 @@ PyTuple_New(register int size)
6060
int nbytes = size * sizeof(PyObject *);
6161
/* Check for overflow */
6262
if (nbytes / sizeof(PyObject *) != (size_t)size ||
63-
(nbytes += sizeof(PyTupleObject) - sizeof(PyObject *))
64-
<= 0)
63+
(nbytes > INT_MAX - sizeof(PyTupleObject) - sizeof(PyObject *)))
6564
{
6665
return PyErr_NoMemory();
6766
}
67+
nbytes += sizeof(PyTupleObject) - sizeof(PyObject *);
68+
6869
op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
6970
if (op == NULL)
7071
return NULL;

Objects/unicodeobject.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ PyUnicodeObject *_PyUnicode_New(int length)
186186
return unicode_empty;
187187
}
188188

189+
/* Ensure we won't overflow the size. */
190+
if (length > ((INT_MAX / sizeof(Py_UNICODE)) - 1)) {
191+
return (PyUnicodeObject *)PyErr_NoMemory();
192+
}
193+
189194
/* Unicode freelist & memory allocation */
190195
if (unicode_freelist) {
191196
unicode = unicode_freelist;
@@ -1040,6 +1045,9 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s,
10401045
char * out;
10411046
char * start;
10421047

1048+
if (cbAllocated / 5 != size)
1049+
return PyErr_NoMemory();
1050+
10431051
if (size == 0)
10441052
return PyString_FromStringAndSize(NULL, 0);
10451053

@@ -1638,6 +1646,7 @@ PyUnicode_EncodeUTF16(const Py_UNICODE *s,
16381646
{
16391647
PyObject *v;
16401648
unsigned char *p;
1649+
int nsize, bytesize;
16411650
#ifdef Py_UNICODE_WIDE
16421651
int i, pairs;
16431652
#else
@@ -1662,8 +1671,15 @@ PyUnicode_EncodeUTF16(const Py_UNICODE *s,
16621671
if (s[i] >= 0x10000)
16631672
pairs++;
16641673
#endif
1665-
v = PyString_FromStringAndSize(NULL,
1666-
2 * (size + pairs + (byteorder == 0)));
1674+
/* 2 * (size + pairs + (byteorder == 0)) */
1675+
if (size > INT_MAX ||
1676+
size > INT_MAX - pairs - (byteorder == 0))
1677+
return PyErr_NoMemory();
1678+
nsize = (size + pairs + (byteorder == 0));
1679+
bytesize = nsize * 2;
1680+
if (bytesize / 2 != nsize)
1681+
return PyErr_NoMemory();
1682+
v = PyString_FromStringAndSize(NULL, bytesize);
16671683
if (v == NULL)
16681684
return NULL;
16691685

@@ -1977,6 +1993,11 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
19771993
char *p;
19781994

19791995
static const char *hexdigit = "0123456789abcdef";
1996+
#ifdef Py_UNICODE_WIDE
1997+
const int expandsize = 10;
1998+
#else
1999+
const int expandsize = 6;
2000+
#endif
19802001

19812002
/* Initial allocation is based on the longest-possible unichr
19822003
escape.
@@ -1992,13 +2013,12 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
19922013
escape.
19932014
*/
19942015

2016+
if (size > (INT_MAX - 2 - 1) / expandsize)
2017+
return PyErr_NoMemory();
2018+
19952019
repr = PyString_FromStringAndSize(NULL,
19962020
2
1997-
#ifdef Py_UNICODE_WIDE
1998-
+ 10*size
1999-
#else
2000-
+ 6*size
2001-
#endif
2021+
+ expandsize*size
20022022
+ 1);
20032023
if (repr == NULL)
20042024
return NULL;
@@ -2239,12 +2259,16 @@ PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s,
22392259
char *q;
22402260

22412261
static const char *hexdigit = "0123456789abcdef";
2242-
22432262
#ifdef Py_UNICODE_WIDE
2244-
repr = PyString_FromStringAndSize(NULL, 10 * size);
2263+
const int expandsize = 10;
22452264
#else
2246-
repr = PyString_FromStringAndSize(NULL, 6 * size);
2265+
const int expandsize = 6;
22472266
#endif
2267+
2268+
if (size > INT_MAX / expandsize)
2269+
return PyErr_NoMemory();
2270+
2271+
repr = PyString_FromStringAndSize(NULL, expandsize * size);
22482272
if (repr == NULL)
22492273
return NULL;
22502274
if (size == 0)
@@ -4289,6 +4313,11 @@ PyUnicodeObject *pad(PyUnicodeObject *self,
42894313
return self;
42904314
}
42914315

4316+
if (left > INT_MAX - self->length ||
4317+
right > INT_MAX - (left + self->length)) {
4318+
PyErr_SetString(PyExc_OverflowError, "padded string is too long");
4319+
return NULL;
4320+
}
42924321
u = _PyUnicode_New(left + self->length + right);
42934322
if (u) {
42944323
if (left)

0 commit comments

Comments
 (0)