diff Modules/arraymodule.c @ 45337:8cbe0bd93c28 2.5

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.
author Martin v. Löwis <martin@v.loewis.de>
date Thu, 14 Feb 2008 11:26:18 +0000
parents 4a03860ae08b
children 4504dfcc1924
line wrap: on
line diff
--- a/Modules/arraymodule.c	Thu Feb 14 04:57:08 2008 +0000
+++ b/Modules/arraymodule.c	Thu Feb 14 11:26:18 2008 +0000
@@ -652,6 +652,9 @@
 		PyErr_BadArgument();
 		return NULL;
 	}
+	if (a->ob_size > PY_SSIZE_T_MAX - b->ob_size) {
+		return PyErr_NoMemory();
+	}
 	size = a->ob_size + b->ob_size;
 	np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
 	if (np == NULL) {
@@ -674,6 +677,9 @@
 	Py_ssize_t nbytes;
 	if (n < 0)
 		n = 0;
+	if ((a->ob_size != 0) && (n > PY_SSIZE_T_MAX / a->ob_size)) {
+		return PyErr_NoMemory();
+	}
 	size = a->ob_size * n;
 	np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
 	if (np == NULL)
@@ -818,6 +824,11 @@
 			     "can only extend with array of same kind");
 		return -1;
 	}
+	if ((self->ob_size > PY_SSIZE_T_MAX - b->ob_size) ||
+		((self->ob_size + b->ob_size) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
+			PyErr_NoMemory();
+			return -1;
+	}
 	size = self->ob_size + b->ob_size;
         PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
         if (self->ob_item == NULL) {
@@ -859,6 +870,10 @@
 		if (n < 0)
 			n = 0;
 		items = self->ob_item;
+		if ((self->ob_descr->itemsize != 0) && 
+			(self->ob_size > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
+			return PyErr_NoMemory();
+		}
 		size = self->ob_size * self->ob_descr->itemsize;
 		if (n == 0) {
 			PyMem_FREE(items);
@@ -867,6 +882,9 @@
 			self->allocated = 0;
 		}
 		else {
+			if (size > PY_SSIZE_T_MAX / n) {
+				return PyErr_NoMemory();
+			}
 			PyMem_Resize(items, char, n * size);
 			if (items == NULL)
 				return PyErr_NoMemory();
@@ -1148,6 +1166,10 @@
 		Py_INCREF(dict);
 	}
 	if (array->ob_size > 0) {
+		if (array->ob_descr->itemsize 
+				> PY_SSIZE_T_MAX / array->ob_size) {
+			return PyErr_NoMemory();
+		}
 		result = Py_BuildValue("O(cs#)O", 
 			array->ob_type, 
 			array->ob_descr->typecode,
@@ -1310,6 +1332,9 @@
 			if ((*self->ob_descr->setitem)(self,
 					self->ob_size - n + i, v) != 0) {
 				self->ob_size -= n;
+				if (itemsize && (self->ob_size > PY_SSIZE_T_MAX / itemsize)) {
+					return PyErr_NoMemory();
+				}
 				PyMem_RESIZE(item, char,
 					          self->ob_size * itemsize);
 				self->ob_item = item;
@@ -1369,6 +1394,10 @@
 	n = n / itemsize;
 	if (n > 0) {
 		char *item = self->ob_item;
+		if ((n > PY_SSIZE_T_MAX - self->ob_size) ||
+			((self->ob_size + n) > PY_SSIZE_T_MAX / itemsize)) {
+				return PyErr_NoMemory();
+		}
 		PyMem_RESIZE(item, char, (self->ob_size + n) * itemsize);
 		if (item == NULL) {
 			PyErr_NoMemory();
@@ -1394,8 +1423,12 @@
 static PyObject *
 array_tostring(arrayobject *self, PyObject *unused)
 {
-	return PyString_FromStringAndSize(self->ob_item,
+	if (self->ob_size <= PY_SSIZE_T_MAX / self->ob_descr->itemsize) {
+		return PyString_FromStringAndSize(self->ob_item,
 				    self->ob_size * self->ob_descr->itemsize);
+	} else {
+		return PyErr_NoMemory();
+	}
 }
 
 PyDoc_STRVAR(tostring_doc,
@@ -1423,6 +1456,9 @@
 	}
 	if (n > 0) {
 		Py_UNICODE *item = (Py_UNICODE *) self->ob_item;
+		if (self->ob_size > PY_SSIZE_T_MAX - n) {
+			return PyErr_NoMemory();
+		}
 		PyMem_RESIZE(item, Py_UNICODE, self->ob_size + n);
 		if (item == NULL) {
 			PyErr_NoMemory();