]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Security patches from Apple: prevent int overflow when allocating memory
authorNeal Norwitz <nnorwitz@gmail.com>
Thu, 31 Jul 2008 17:04:32 +0000 (17:04 +0000)
committerNeal Norwitz <nnorwitz@gmail.com>
Thu, 31 Jul 2008 17:04:32 +0000 (17:04 +0000)
Misc/NEWS
Modules/gcmodule.c
Modules/mmapmodule.c
Modules/stropmodule.c
Objects/bufferobject.c
Objects/stringobject.c
Objects/tupleobject.c
Objects/unicodeobject.c

index 517849208cfedb157dbb5523ba2de2de130c09ea..7b504b328bd9d189164fe1bd562c36520c977b32 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,8 @@ What's New in Python 2.4.5c1?
 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 e8971b0d2b646693a77e7ca7e9f12642183eec53..c9ba429105132124c67d3b5d9237fa6a7294b151 100644 (file)
@@ -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 nitems)
 {
        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();
index ac647bfadb18fce2342c4aac95992549d0a12983..7bcf4c8a8b0e6b021bef50b8abc30dea1c953ae1 100644 (file)
@@ -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 e0d686b1a39b918856fafbe0eb5218fb4b599d06..6528eb18e8cface1c948509720b435bd9fa6f5e1 100644 (file)
@@ -214,6 +214,13 @@ strop_joinfields(PyObject *self, PyObject *args)
                                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, PyObject *args)
                        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 53bcb1e94ccbdc09499903b76370aa69421564e8..9639e8aa41459d5b7c8d6d52e1fe74259799b2cf 100644 (file)
@@ -384,6 +384,10 @@ buffer_repeat(PyBufferObject *self, int count)
                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 7395010e1629c7e272f4a8ae91b857c8b9fce4fd..ee1c3bf8257e5914e16512c336ac2be45020b535 100644 (file)
@@ -69,6 +69,11 @@ PyString_FromStringAndSize(const char *str, int size)
                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, register PyObject *bb)
                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 74b905626c1735c88a16bf4345233b8c598988fd..bb0cd66538afa9fb6cbdb691af848fabd0125e7e 100644 (file)
@@ -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 880b9ac612db981d340f0cd5a69630d27efc407e..b29e7ff5442e423cf00e85262f3480e83d941e5f 100644 (file)
@@ -186,6 +186,11 @@ PyUnicodeObject *_PyUnicode_New(int length)
         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_UNICODE *s,
     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 *s,
 {
     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 *s,
        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_UNICODE *s,
     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_UNICODE *s,
        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_EncodeRawUnicodeEscape(const Py_UNICODE *s,
     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 *self,
         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)