Index: Python-2.4.4/Objects/unicodeobject.c =================================================================== --- Python-2.4.4.orig/Objects/unicodeobject.c +++ Python-2.4.4/Objects/unicodeobject.c @@ -186,6 +186,11 @@ PyUnicodeObject *_PyUnicode_New(int leng return unicode_empty; } + /* Ensure we won't overflow the size. */ + if (length > ((INT_MAX / sizeof(Py_UNICODE)) - 1)) { + return (PyUnicodeObject *)PyErr_NoMemory(); + } + /* Unicode freelist & memory allocation */ if (unicode_freelist) { unicode = unicode_freelist; @@ -1040,6 +1045,9 @@ PyObject *PyUnicode_EncodeUTF7(const Py_ char * out; char * start; + if (cbAllocated / 5 != size) + return PyErr_NoMemory(); + if (size == 0) return PyString_FromStringAndSize(NULL, 0); @@ -1638,6 +1646,7 @@ PyUnicode_EncodeUTF16(const Py_UNICODE * { PyObject *v; unsigned char *p; + int nsize, bytesize; #ifdef Py_UNICODE_WIDE int i, pairs; #else @@ -1662,8 +1671,15 @@ PyUnicode_EncodeUTF16(const Py_UNICODE * if (s[i] >= 0x10000) pairs++; #endif - v = PyString_FromStringAndSize(NULL, - 2 * (size + pairs + (byteorder == 0))); + /* 2 * (size + pairs + (byteorder == 0)) */ + if (size > INT_MAX || + size > INT_MAX - pairs - (byteorder == 0)) + return PyErr_NoMemory(); + nsize = (size + pairs + (byteorder == 0)); + bytesize = nsize * 2; + if (bytesize / 2 != nsize) + return PyErr_NoMemory(); + v = PyString_FromStringAndSize(NULL, bytesize); if (v == NULL) return NULL; @@ -1977,6 +1993,11 @@ PyObject *unicodeescape_string(const Py_ char *p; static const char *hexdigit = "0123456789abcdef"; +#ifdef Py_UNICODE_WIDE + const int expandsize = 10; +#else + const int expandsize = 6; +#endif /* Initial allocation is based on the longest-possible unichr escape. @@ -1992,13 +2013,12 @@ PyObject *unicodeescape_string(const Py_ escape. */ + if (size > (INT_MAX - 2 - 1) / expandsize) + return PyErr_NoMemory(); + repr = PyString_FromStringAndSize(NULL, 2 -#ifdef Py_UNICODE_WIDE - + 10*size -#else - + 6*size -#endif + + expandsize*size + 1); if (repr == NULL) return NULL; @@ -2239,12 +2259,16 @@ PyObject *PyUnicode_EncodeRawUnicodeEsca char *q; static const char *hexdigit = "0123456789abcdef"; - #ifdef Py_UNICODE_WIDE - repr = PyString_FromStringAndSize(NULL, 10 * size); + const int expandsize = 10; #else - repr = PyString_FromStringAndSize(NULL, 6 * size); + const int expandsize = 6; #endif + + if (size > INT_MAX / expandsize) + return PyErr_NoMemory(); + + repr = PyString_FromStringAndSize(NULL, expandsize * size); if (repr == NULL) return NULL; if (size == 0) @@ -4289,6 +4313,11 @@ PyUnicodeObject *pad(PyUnicodeObject *se return self; } + if (left > INT_MAX - self->length || + right > INT_MAX - (left + self->length)) { + PyErr_SetString(PyExc_OverflowError, "padded string is too long"); + return NULL; + } u = _PyUnicode_New(left + self->length + right); if (u) { if (left) Index: Python-2.4.4/Objects/tupleobject.c =================================================================== --- Python-2.4.4.orig/Objects/tupleobject.c +++ Python-2.4.4/Objects/tupleobject.c @@ -60,11 +60,12 @@ PyTuple_New(register int size) int nbytes = size * sizeof(PyObject *); /* Check for overflow */ if (nbytes / sizeof(PyObject *) != (size_t)size || - (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *)) - <= 0) + (nbytes > INT_MAX - sizeof(PyTupleObject) - sizeof(PyObject *))) { return PyErr_NoMemory(); } + nbytes += sizeof(PyTupleObject) - sizeof(PyObject *); + op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size); if (op == NULL) return NULL; Index: Python-2.4.4/Objects/bufferobject.c =================================================================== --- Python-2.4.4.orig/Objects/bufferobject.c +++ Python-2.4.4/Objects/bufferobject.c @@ -384,6 +384,10 @@ buffer_repeat(PyBufferObject *self, int count = 0; if (!get_buf(self, &ptr, &size)) return NULL; + if (count > INT_MAX / size) { + PyErr_SetString(PyExc_MemoryError, "result too large"); + return NULL; + } ob = PyString_FromStringAndSize(NULL, size * count); if ( ob == NULL ) return NULL; Index: Python-2.4.4/Objects/stringobject.c =================================================================== --- Python-2.4.4.orig/Objects/stringobject.c +++ Python-2.4.4/Objects/stringobject.c @@ -69,6 +69,11 @@ PyString_FromStringAndSize(const char *s return (PyObject *)op; } + if (size > INT_MAX - sizeof(PyStringObject)) { + PyErr_SetString(PyExc_OverflowError, "string is too large"); + return NULL; + } + /* Inline PyObject_NewVar */ op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size); if (op == NULL) @@ -104,7 +109,7 @@ PyString_FromString(const char *str) assert(str != NULL); size = strlen(str); - if (size > INT_MAX) { + if (size > INT_MAX - sizeof(PyStringObject)) { PyErr_SetString(PyExc_OverflowError, "string is too long for a Python string"); return NULL; @@ -907,7 +912,18 @@ string_concat(register PyStringObject *a Py_INCREF(a); return (PyObject *)a; } + /* Check that string sizes are not negative, to prevent an + overflow in cases where we are passed incorrectly-created + strings with negative lengths (due to a bug in other code). + */ size = a->ob_size + b->ob_size; + if (a->ob_size < 0 || b->ob_size < 0 || + a->ob_size > INT_MAX - b->ob_size) { + PyErr_SetString(PyExc_OverflowError, + "strings are too large to concat"); + return NULL; + } + /* Inline PyObject_NewVar */ op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size); if (op == NULL) Index: Python-2.4.4/Misc/NEWS =================================================================== --- Python-2.4.4.orig/Misc/NEWS +++ Python-2.4.4/Misc/NEWS @@ -23,6 +23,8 @@ What's New in Python 2.4.4c1? Core and builtins ----------------- +- Apply security patches from Apple. + - Issue #2620: Overflow checking when allocating or reallocating memory was not always being done properly in some python types and extension modules. PyMem_MALLOC, PyMem_REALLOC, PyMem_NEW and PyMem_RESIZE have Index: Python-2.4.4/Modules/mmapmodule.c =================================================================== --- Python-2.4.4.orig/Modules/mmapmodule.c +++ Python-2.4.4/Modules/mmapmodule.c @@ -223,7 +223,7 @@ mmap_read_method(mmap_object *self, return(NULL); /* silently 'adjust' out-of-range requests */ - if ((self->pos + num_bytes) > self->size) { + if (num_bytes > self->size - self->pos) { num_bytes -= (self->pos+num_bytes) - self->size; } result = Py_BuildValue("s#", self->data+self->pos, num_bytes); Index: Python-2.4.4/Modules/stropmodule.c =================================================================== --- Python-2.4.4.orig/Modules/stropmodule.c +++ Python-2.4.4/Modules/stropmodule.c @@ -214,6 +214,13 @@ strop_joinfields(PyObject *self, PyObjec return NULL; } slen = PyString_GET_SIZE(item); + if (slen > INT_MAX - reslen || + seplen > INT_MAX - reslen - seplen) { + PyErr_SetString(PyExc_OverflowError, + "input too long"); + Py_DECREF(res); + return NULL; + } while (reslen + slen + seplen >= sz) { if (_PyString_Resize(&res, sz * 2) < 0) return NULL; @@ -251,6 +258,14 @@ strop_joinfields(PyObject *self, PyObjec return NULL; } slen = PyString_GET_SIZE(item); + if (slen > INT_MAX - reslen || + seplen > INT_MAX - reslen - seplen) { + PyErr_SetString(PyExc_OverflowError, + "input too long"); + Py_DECREF(res); + Py_XDECREF(item); + return NULL; + } while (reslen + slen + seplen >= sz) { if (_PyString_Resize(&res, sz * 2) < 0) { Py_DECREF(item); Index: Python-2.4.4/Modules/gcmodule.c =================================================================== --- Python-2.4.4.orig/Modules/gcmodule.c +++ Python-2.4.4/Modules/gcmodule.c @@ -1249,7 +1249,10 @@ PyObject * _PyObject_GC_Malloc(size_t basicsize) { PyObject *op; - PyGC_Head *g = PyObject_MALLOC(sizeof(PyGC_Head) + basicsize); + PyGC_Head *g; + if (basicsize > INT_MAX - sizeof(PyGC_Head)) + return PyErr_NoMemory(); + g = PyObject_MALLOC(sizeof(PyGC_Head) + basicsize); if (g == NULL) return PyErr_NoMemory(); g->gc.gc_refs = GC_UNTRACKED; @@ -1291,6 +1294,8 @@ _PyObject_GC_Resize(PyVarObject *op, int { const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems); PyGC_Head *g = AS_GC(op); + if (basicsize > INT_MAX - sizeof(PyGC_Head)) + return (PyVarObject *)PyErr_NoMemory(); g = PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); if (g == NULL) return (PyVarObject *)PyErr_NoMemory();