[Python-checkins] cpython (3.4): Issue #19687: Fixed possible integer overflows in ElementTree.

serhiy.storchaka python-checkins at python.org
Wed Nov 25 13:18:52 EST 2015


https://hg.python.org/cpython/rev/e5eac1d692ad
changeset:   99360:e5eac1d692ad
branch:      3.4
parent:      99356:eed36e19f8b8
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Wed Nov 25 20:12:37 2015 +0200
summary:
  Issue #19687: Fixed possible integer overflows in ElementTree.
Based on patch by Christian Heimes.

files:
  Modules/_elementtree.c |  44 +++++++++++++++++++++++------
  1 files changed, 34 insertions(+), 10 deletions(-)


diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -429,9 +429,9 @@
 }
 
 LOCAL(int)
-element_resize(ElementObject* self, int extra)
+element_resize(ElementObject* self, Py_ssize_t extra)
 {
-    int size;
+    Py_ssize_t size;
     PyObject* *children;
 
     /* make sure self->children can hold the given number of extra
@@ -453,6 +453,13 @@
          * be safe.
          */
         size = size ? size : 1;
+        if ((size_t)size > PY_SSIZE_T_MAX/sizeof(PyObject*))
+            goto nomemory;
+        if (size > INT_MAX) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "too many children");
+            return -1;
+        }
         if (self->extra->children != self->extra->_children) {
             /* Coverity CID #182 size_error: Allocating 1 bytes to pointer
              * "children", which needs at least 4 bytes. Although it's a
@@ -889,7 +896,7 @@
                                  PyObject *tail,
                                  PyObject *children)
 {
-    Py_ssize_t i, nchildren;
+    int i, nchildren;
 
     if (!tag) {
         PyErr_SetString(PyExc_TypeError, "tag may not be NULL");
@@ -914,11 +921,18 @@
 
     /* Compute 'nchildren'. */
     if (children) {
+        Py_ssize_t size;
         if (!PyList_Check(children)) {
             PyErr_SetString(PyExc_TypeError, "'_children' is not a list");
             return NULL;
         }
-        nchildren = PyList_Size(children);
+        size = PyList_Size(children);
+        /* expat limits nchildren to int */
+        if (size > INT_MAX) {
+            PyErr_SetString(PyExc_OverflowError, "too many children");
+            return NULL;
+        }
+        nchildren = (int)size;
     }
     else {
         nchildren = 0;
@@ -1505,18 +1519,19 @@
 }
 
 static int
-element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item)
+element_setitem(PyObject* self_, Py_ssize_t index_, PyObject* item)
 {
     ElementObject* self = (ElementObject*) self_;
-    int i;
+    int i, index;
     PyObject* old;
 
-    if (!self->extra || index < 0 || index >= self->extra->length) {
+    if (!self->extra || index_ < 0 || index_ >= self->extra->length) {
         PyErr_SetString(
             PyExc_IndexError,
             "child assignment index out of range");
         return -1;
     }
+    index = (int)index_;
 
     old = self->extra->children[index];
 
@@ -1617,6 +1632,7 @@
                 &start, &stop, &step, &slicelen) < 0) {
             return -1;
         }
+        assert(slicelen <= self->extra->length);
 
         if (value == NULL) {
             /* Delete slice */
@@ -1678,7 +1694,7 @@
                     (self->extra->length - cur) * sizeof(PyObject *));
             }
 
-            self->extra->length -= slicelen;
+            self->extra->length -= (int)slicelen;
 
             /* Discard the recycle list with all the deleted sub-elements */
             Py_XDECREF(recycle);
@@ -1714,6 +1730,8 @@
                 return -1;
             }
         }
+        assert(newlen - slicelen <= INT_MAX - self->extra->length);
+        assert(newlen - slicelen >= -self->extra->length);
 
         if (slicelen > 0) {
             /* to avoid recursive calls to this method (via decref), move
@@ -1747,7 +1765,7 @@
             self->extra->children[cur] = element;
         }
 
-        self->extra->length += newlen - slicelen;
+        self->extra->length += (int)(newlen - slicelen);
 
         Py_DECREF(seq);
 
@@ -3528,8 +3546,14 @@
             break;
         }
 
+        if (PyBytes_GET_SIZE(buffer) > INT_MAX) {
+            Py_DECREF(buffer);
+            Py_DECREF(reader);
+            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
+            return NULL;
+        }
         res = expat_parse(
-            self, PyBytes_AS_STRING(buffer), PyBytes_GET_SIZE(buffer), 0
+            self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0
             );
 
         Py_DECREF(buffer);

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list