Closes release blocker #3627.

Merged revisions 65335 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

TESTED=./python -E -tt ./Lib/test/regrtest.py -uall (both debug and opt)

........
  r65335 | neal.norwitz | 2008-07-31 10:17:14 -0700 (Thu, 31 Jul 2008) | 1 line

  Security patches from Apple:  prevent int overflow when allocating memory
........
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index da11249..201d294 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -121,6 +121,11 @@
         return NULL;
     }
 
+    /* Prevent buffer overflow when setting alloc to size+1. */
+    if (size == PY_SSIZE_T_MAX) {
+        return PyErr_NoMemory();
+    }
+
     new = PyObject_New(PyByteArrayObject, &PyByteArray_Type);
     if (new == NULL)
         return NULL;
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index bfb4ff8..24228ea 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -83,6 +83,12 @@
 		return (PyObject *)op;
 	}
 
+	if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) {
+		PyErr_SetString(PyExc_OverflowError,
+				"byte string is too large");
+		return NULL;
+	}
+
 	/* Inline PyObject_NewVar */
 	op = (PyBytesObject *)PyObject_MALLOC(sizeof(PyBytesObject) + size);
 	if (op == NULL)
@@ -111,7 +117,7 @@
 
 	assert(str != NULL);
 	size = strlen(str);
-	if (size > PY_SSIZE_T_MAX) {
+	if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) {
 		PyErr_SetString(PyExc_OverflowError,
 			"byte string is too long");
 		return NULL;
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 3aa518b..8f7ad4c 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -139,6 +139,8 @@
 		PyErr_NoMemory();
 		return NULL;
 	}
+	/* XXX(nnorwitz): This can overflow --
+           PyObject_NEW_VAR / _PyObject_VAR_SIZE need to detect overflow */
 	return (PyLongObject*)PyObject_INIT_VAR(result, &PyLong_Type, size);
 }
 
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 7ff957e..963d90e 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -60,11 +60,12 @@
 		Py_ssize_t nbytes = size * sizeof(PyObject *);
 		/* Check for overflow */
 		if (nbytes / sizeof(PyObject *) != (size_t)size ||
-		    (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *))
-		    <= 0)
+		    (nbytes > PY_SSIZE_T_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;
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index c85a063..847b61d 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -311,6 +311,11 @@
         return unicode_empty;
     }
 
+    /* Ensure we won't overflow the size. */
+    if (length > ((PY_SSIZE_T_MAX / sizeof(Py_UNICODE)) - 1)) {
+        return (PyUnicodeObject *)PyErr_NoMemory();
+    }
+
     /* Unicode freelist & memory allocation */
     if (free_list) {
         unicode = free_list;
@@ -1860,6 +1865,9 @@
     if (size == 0)
        return PyBytes_FromStringAndSize(NULL, 0);
 
+    if (cbAllocated / 5 != size)
+        return PyErr_NoMemory();
+
     v = PyByteArray_FromStringAndSize(NULL, cbAllocated);
     if (v == NULL)
         return NULL;
@@ -2452,8 +2460,9 @@
 {
     PyObject *v, *result;
     unsigned char *p;
+    Py_ssize_t nsize, bytesize;
 #ifndef Py_UNICODE_WIDE
-    int i, pairs;
+    Py_ssize_t i, pairs;
 #else
     const int pairs = 0;
 #endif
@@ -2481,8 +2490,11 @@
 	    0xDC00 <= s[i+1] && s[i+1] <= 0xDFFF)
 	    pairs++;
 #endif
-    v = PyByteArray_FromStringAndSize(NULL,
-		  4 * (size - pairs + (byteorder == 0)));
+    nsize = (size - pairs + (byteorder == 0));
+    bytesize = nsize * 4;
+    if (bytesize / 4 != nsize)
+	return PyErr_NoMemory();
+    v = PyByteArray_FromStringAndSize(NULL, bytesize);
     if (v == NULL)
         return NULL;
 
@@ -2726,8 +2738,9 @@
 {
     PyObject *v, *result;
     unsigned char *p;
+    Py_ssize_t nsize, bytesize;
 #ifdef Py_UNICODE_WIDE
-    int i, pairs;
+    Py_ssize_t i, pairs;
 #else
     const int pairs = 0;
 #endif
@@ -2750,8 +2763,15 @@
 	if (s[i] >= 0x10000)
 	    pairs++;
 #endif
-    v = PyByteArray_FromStringAndSize(NULL,
-		  2 * (size + pairs + (byteorder == 0)));
+    /* 2 * (size + pairs + (byteorder == 0)) */
+    if (size > PY_SSIZE_T_MAX ||
+        size > PY_SSIZE_T_MAX - pairs - (byteorder == 0))
+	return PyErr_NoMemory();
+    nsize = size + pairs + (byteorder == 0);
+    bytesize = nsize * 2;
+    if (bytesize / 2 != nsize)
+	return PyErr_NoMemory();
+    v = PyByteArray_FromStringAndSize(NULL, bytesize);
     if (v == NULL)
         return NULL;
 
@@ -3082,6 +3102,12 @@
     PyObject *repr, *result;
     char *p;
 
+#ifdef Py_UNICODE_WIDE
+    const Py_ssize_t expandsize = 10;
+#else
+    const Py_ssize_t expandsize = 6;
+#endif
+
     /* XXX(nnorwitz): rather than over-allocating, it would be
        better to choose a different scheme.  Perhaps scan the
        first N-chars of the string and allocate based on that size.
@@ -3100,12 +3126,12 @@
        escape.
     */
 
+    if (size > (PY_SSIZE_T_MAX - 2 - 1) / expandsize)
+	return PyErr_NoMemory();
+
     repr = PyByteArray_FromStringAndSize(NULL,
-#ifdef Py_UNICODE_WIDE
-        + 10*size
-#else
-        + 6*size
-#endif
+        2
+        + expandsize*size
         + 1);
     if (repr == NULL)
         return NULL;
@@ -3353,10 +3379,15 @@
     char *q;
 
 #ifdef Py_UNICODE_WIDE
-    repr = PyByteArray_FromStringAndSize(NULL, 10 * size);
+    const Py_ssize_t expandsize = 10;
 #else
-    repr = PyByteArray_FromStringAndSize(NULL, 6 * size);
+    const Py_ssize_t expandsize = 6;
 #endif
+    
+    if (size > PY_SSIZE_T_MAX / expandsize)
+	return PyErr_NoMemory();
+    
+    repr = PyByteArray_FromStringAndSize(NULL, expandsize * size);
     if (repr == NULL)
         return NULL;
     if (size == 0)
@@ -5747,6 +5778,11 @@
         return self;
     }
 
+    if (left > PY_SSIZE_T_MAX - self->length ||
+        right > PY_SSIZE_T_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)