summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorNeal Norwitz <nnorwitz@gmail.com>2008-07-31 17:17:14 (GMT)
committerNeal Norwitz <nnorwitz@gmail.com>2008-07-31 17:17:14 (GMT)
commite7d8be80ba634fa15ece6f503c33592e0d333361 (patch)
tree4264163ebdcea24504f3842330602d98301cf659 /Objects
parente70f8e1205b5fc60a30469db69bbee4d5d532d86 (diff)
downloadcpython-e7d8be80ba634fa15ece6f503c33592e0d333361.zip
cpython-e7d8be80ba634fa15ece6f503c33592e0d333361.tar.gz
cpython-e7d8be80ba634fa15ece6f503c33592e0d333361.tar.bz2
Security patches from Apple: prevent int overflow when allocating memory
Diffstat (limited to 'Objects')
-rw-r--r--Objects/bufferobject.c4
-rw-r--r--Objects/longobject.c2
-rw-r--r--Objects/stringobject.c19
-rw-r--r--Objects/tupleobject.c5
-rw-r--r--Objects/unicodeobject.c61
5 files changed, 73 insertions, 18 deletions
diff --git a/Objects/bufferobject.c b/Objects/bufferobject.c
index 3bd8c6b..9a5c39f 100644
--- a/Objects/bufferobject.c
+++ b/Objects/bufferobject.c
@@ -431,6 +431,10 @@ buffer_repeat(PyBufferObject *self, Py_ssize_t count)
count = 0;
if (!get_buf(self, &ptr, &size, ANY_BUFFER))
return NULL;
+ if (count > PY_SSIZE_T_MAX / size) {
+ PyErr_SetString(PyExc_MemoryError, "result too large");
+ return NULL;
+ }
ob = PyString_FromStringAndSize(NULL, size * count);
if ( ob == NULL )
return NULL;
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 2c228bb..228376a 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -70,6 +70,8 @@ _PyLong_New(Py_ssize_t size)
return NULL;
}
/* coverity[ampersand_in_size] */
+ /* XXX(nnorwitz): This can overflow --
+ PyObject_NEW_VAR / _PyObject_VAR_SIZE need to detect overflow */
return PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
}
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 793cc88..0d2ceb1 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -74,6 +74,11 @@ PyString_FromStringAndSize(const char *str, Py_ssize_t size)
return (PyObject *)op;
}
+ if (size > PY_SSIZE_T_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)
@@ -109,7 +114,7 @@ PyString_FromString(const char *str)
assert(str != NULL);
size = strlen(str);
- if (size > PY_SSIZE_T_MAX) {
+ if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) {
PyErr_SetString(PyExc_OverflowError,
"string is too long for a Python string");
return NULL;
@@ -977,13 +982,23 @@ string_concat(register PyStringObject *a, register PyObject *bb)
return (PyObject *)a;
}
size = Py_SIZE(a) + Py_SIZE(b);
- if (size < 0) {
+ /* 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).
+ */
+ if (Py_SIZE(a) < 0 || Py_SIZE(b) < 0 ||
+ Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b)) {
PyErr_SetString(PyExc_OverflowError,
"strings are too large to concat");
return NULL;
}
/* Inline PyObject_NewVar */
+ if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "strings are too large to concat");
+ return NULL;
+ }
op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
if (op == NULL)
return PyErr_NoMemory();
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 79d7553..348ae8c 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -60,11 +60,12 @@ PyTuple_New(register Py_ssize_t size)
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 16d97c3..7abf984 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -299,6 +299,11 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
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;
@@ -1651,6 +1656,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);
@@ -2245,8 +2253,9 @@ PyUnicode_EncodeUTF32(const Py_UNICODE *s,
{
PyObject *v;
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
@@ -2274,8 +2283,11 @@ PyUnicode_EncodeUTF32(const Py_UNICODE *s,
0xDC00 <= s[i+1] && s[i+1] <= 0xDFFF)
pairs++;
#endif
- v = PyString_FromStringAndSize(NULL,
- 4 * (size - pairs + (byteorder == 0)));
+ nsize = (size - pairs + (byteorder == 0));
+ bytesize = nsize * 4;
+ if (bytesize / 4 != nsize)
+ return PyErr_NoMemory();
+ v = PyString_FromStringAndSize(NULL, bytesize);
if (v == NULL)
return NULL;
@@ -2515,8 +2527,9 @@ PyUnicode_EncodeUTF16(const Py_UNICODE *s,
{
PyObject *v;
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
@@ -2539,8 +2552,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 > 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 = PyString_FromStringAndSize(NULL, bytesize);
if (v == NULL)
return NULL;
@@ -2868,6 +2888,11 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
char *p;
static const char *hexdigit = "0123456789abcdef";
+#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
@@ -2887,13 +2912,12 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
escape.
*/
+ if (size > (PY_SSIZE_T_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;
@@ -3146,12 +3170,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 Py_ssize_t expandsize = 10;
#else
- repr = PyString_FromStringAndSize(NULL, 6 * size);
+ const Py_ssize_t expandsize = 6;
#endif
+
+ if (size > PY_SSIZE_T_MAX / expandsize)
+ return PyErr_NoMemory();
+
+ repr = PyString_FromStringAndSize(NULL, expandsize * size);
if (repr == NULL)
return NULL;
if (size == 0)
@@ -5574,6 +5602,11 @@ PyUnicodeObject *pad(PyUnicodeObject *self,
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)