]> granicus.if.org Git - python/commitdiff
Fix for bug 113934. string*n and unicode*n did no overflow checking at
authorTim Peters <tim.peters@gmail.com>
Sat, 9 Sep 2000 06:13:41 +0000 (06:13 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 9 Sep 2000 06:13:41 +0000 (06:13 +0000)
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).

Objects/stringobject.c
Objects/unicodeobject.c

index f7c3f4b157d8adc49d3d4cfd31aec26bd4ba2a59..eee355173a7b9bb1905137ccaaf37fcf781c9855 100644 (file)
@@ -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);
index 8ed638020852eb921be904270a5ab01f8e28ce2c..76bb92a117f041fde0169aea032fa07f680e2bfc 100644 (file)
@@ -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;