diff options
author | Tim Peters <tim.peters@gmail.com> | 2000-09-09 06:13:41 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2000-09-09 06:13:41 (GMT) |
commit | 8f422461b4c19b8a66beae218311917e688f03ce (patch) | |
tree | b6a577d50d437b8e2d388f5892fcd1f645d2c84c | |
parent | 643d76d735726352dd40433b663d48617e27e200 (diff) | |
download | cpython-8f422461b4c19b8a66beae218311917e688f03ce.zip cpython-8f422461b4c19b8a66beae218311917e688f03ce.tar.gz cpython-8f422461b4c19b8a66beae218311917e688f03ce.tar.bz2 |
Fix for bug 113934. string*n and unicode*n did no overflow checking at
all, either to see whether the # of chars fit in an int, or that the
amount of memory needed fit in a size_t. Checking these is expensive, but
the alternative is silently wrong answers (as in the bug report) or
core dumps (which were easy to provoke using Unicode strings).
-rw-r--r-- | Objects/stringobject.c | 19 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 21 |
2 files changed, 36 insertions, 4 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c index f7c3f4b..eee3551 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -393,16 +393,31 @@ string_repeat(register PyStringObject *a, register int n) register int i; register int size; register PyStringObject *op; + size_t nbytes; if (n < 0) n = 0; + /* watch out for overflows: the size can overflow int, + * and the # of bytes needed can overflow size_t + */ size = a->ob_size * n; + if (n && size / n != a->ob_size) { + PyErr_SetString(PyExc_OverflowError, + "repeated string is too long"); + return NULL; + } if (size == a->ob_size) { Py_INCREF(a); return (PyObject *)a; } - /* PyObject_NewVar is inlined */ + nbytes = size * sizeof(char); + if (nbytes / sizeof(char) != (size_t)size || + nbytes + sizeof(PyStringObject) <= nbytes) { + PyErr_SetString(PyExc_OverflowError, + "repeated string is too long"); + return NULL; + } op = (PyStringObject *) - PyObject_MALLOC(sizeof(PyStringObject) + size * sizeof(char)); + PyObject_MALLOC(sizeof(PyStringObject) + nbytes); if (op == NULL) return PyErr_NoMemory(); PyObject_INIT_VAR(op, &PyString_Type, size); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 8ed6380..76bb92a 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3993,6 +3993,8 @@ unicode_repeat(PyUnicodeObject *str, int len) { PyUnicodeObject *u; Py_UNICODE *p; + int nchars; + size_t nbytes; if (len < 0) len = 0; @@ -4002,8 +4004,23 @@ unicode_repeat(PyUnicodeObject *str, int len) Py_INCREF(str); return (PyObject*) str; } - - u = _PyUnicode_New(len * str->length); + + /* ensure # of chars needed doesn't overflow int and # of bytes + * needed doesn't overflow size_t + */ + nchars = len * str->length; + if (len && nchars / len != str->length) { + PyErr_SetString(PyExc_OverflowError, + "repeated string is too long"); + return NULL; + } + nbytes = (nchars + 1) * sizeof(Py_UNICODE); + if (nbytes / sizeof(Py_UNICODE) != (size_t)(nchars + 1)) { + PyErr_SetString(PyExc_OverflowError, + "repeated string is too long"); + return NULL; + } + u = _PyUnicode_New(nchars); if (!u) return NULL; |