]> granicus.if.org Git - python/commitdiff
Issue #24091: Fixed various crashes in corner cases in cElementTree.
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 18 May 2015 15:28:57 +0000 (18:28 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 18 May 2015 15:28:57 +0000 (18:28 +0300)
Misc/NEWS
Modules/_elementtree.c

index 2726077293c9852b4cefdfaece1a4f2849c24288..a666032ded4d76976b535cbf608884ef0fc3fdff 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -15,6 +15,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #24091: Fixed various crashes in corner cases in cElementTree.
+
 - Issue #15267: HTTPConnection.request() now is compatibile with old-style
   classes (such as TemporaryFile).  Original patch by Atsuo Ishimoto.
 
index 3e9f9dfdc12ef6e8afc670708a8c9091239684d3..837164cd4b4a551e5cc589d2c394e18958d7ed22 100644 (file)
@@ -756,7 +756,7 @@ static PyObject*
 element_extend(ElementObject* self, PyObject* args)
 {
     PyObject* seq;
-    Py_ssize_t i, seqlen = 0;
+    Py_ssize_t i;
 
     PyObject* seq_in;
     if (!PyArg_ParseTuple(args, "O:extend", &seq_in))
@@ -771,8 +771,7 @@ element_extend(ElementObject* self, PyObject* args)
         return NULL;
     }
 
-    seqlen = PySequence_Size(seq);
-    for (i = 0; i < seqlen; i++) {
+    for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) {
         PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
         if (element_add_subelement(self, element) < 0) {
             Py_DECREF(seq);
@@ -805,11 +804,16 @@ element_find(ElementObject* self, PyObject* args)
         
     for (i = 0; i < self->extra->length; i++) {
         PyObject* item = self->extra->children[i];
-        if (Element_CheckExact(item) &&
-            PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) {
-            Py_INCREF(item);
+        int rc;
+        if (!Element_CheckExact(item))
+            continue;
+        Py_INCREF(item);
+        rc = PyObject_Compare(((ElementObject*)item)->tag, tag);
+        if (rc == 0)
             return item;
-        }
+        Py_DECREF(item);
+        if (rc < 0 && PyErr_Occurred())
+            return NULL;
     }
 
     Py_RETURN_NONE;
@@ -838,13 +842,24 @@ element_findtext(ElementObject* self, PyObject* args)
 
     for (i = 0; i < self->extra->length; i++) {
         ElementObject* item = (ElementObject*) self->extra->children[i];
-        if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) {
+        int rc;
+        if (!Element_CheckExact(item))
+            continue;
+        Py_INCREF(item);
+        rc = PyObject_Compare(item->tag, tag);
+        if (rc == 0) {
             PyObject* text = element_get_text(item);
-            if (text == Py_None)
+            if (text == Py_None) {
+                Py_DECREF(item);
                 return PyString_FromString("");
+            }
             Py_XINCREF(text);
+            Py_DECREF(item);
             return text;
         }
+        Py_DECREF(item);
+        if (rc < 0 && PyErr_Occurred())
+            return NULL;
     }
 
     Py_INCREF(default_value);
@@ -876,12 +891,17 @@ element_findall(ElementObject* self, PyObject* args)
 
     for (i = 0; i < self->extra->length; i++) {
         PyObject* item = self->extra->children[i];
-        if (Element_CheckExact(item) &&
-            PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) {
-            if (PyList_Append(out, item) < 0) {
-                Py_DECREF(out);
-                return NULL;
-            }
+        int rc;
+        if (!Element_CheckExact(item))
+            continue;
+        Py_INCREF(item);
+        rc = PyObject_Compare(((ElementObject*)item)->tag, tag);
+        if (rc == 0)
+            rc = PyList_Append(out, item);
+        Py_DECREF(item);
+        if (rc < 0 && PyErr_Occurred()) {
+            Py_DECREF(out);
+            return NULL;
         }
     }
 
@@ -1147,8 +1167,10 @@ static PyObject*
 element_remove(ElementObject* self, PyObject* args)
 {
     int i;
-
+    int rc;
     PyObject* element;
+    PyObject* found;
+
     if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element))
         return NULL;
 
@@ -1164,11 +1186,14 @@ element_remove(ElementObject* self, PyObject* args)
     for (i = 0; i < self->extra->length; i++) {
         if (self->extra->children[i] == element)
             break;
-        if (PyObject_Compare(self->extra->children[i], element) == 0)
+        rc = PyObject_Compare(self->extra->children[i], element);
+        if (rc == 0)
             break;
+        if (rc < 0 && PyErr_Occurred())
+            return NULL;
     }
 
-    if (i == self->extra->length) {
+    if (i >= self->extra->length) {
         /* element is not in children, so raise exception */
         PyErr_SetString(
             PyExc_ValueError,
@@ -1177,13 +1202,13 @@ element_remove(ElementObject* self, PyObject* args)
         return NULL;
     }
 
-    Py_DECREF(self->extra->children[i]);
+    found = self->extra->children[i];
 
     self->extra->length--;
-
     for (; i < self->extra->length; i++)
         self->extra->children[i] = self->extra->children[i+1];
 
+    Py_DECREF(found);
     Py_RETURN_NONE;
 }