diff options
author | Neal Norwitz <nnorwitz@gmail.com> | 2008-07-31 17:17:14 (GMT) |
---|---|---|
committer | Neal Norwitz <nnorwitz@gmail.com> | 2008-07-31 17:17:14 (GMT) |
commit | e7d8be80ba634fa15ece6f503c33592e0d333361 (patch) | |
tree | 4264163ebdcea24504f3842330602d98301cf659 /Objects | |
parent | e70f8e1205b5fc60a30469db69bbee4d5d532d86 (diff) | |
download | cpython-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.c | 4 | ||||
-rw-r--r-- | Objects/longobject.c | 2 | ||||
-rw-r--r-- | Objects/stringobject.c | 19 | ||||
-rw-r--r-- | Objects/tupleobject.c | 5 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 61 |
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) |