mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
Issue #24091: Fixed various crashes in corner cases in C implementation of
ElementTree.
This commit is contained in:
commit
a2c145c2f3
3 changed files with 221 additions and 46 deletions
|
|
@ -1094,7 +1094,7 @@ _elementtree_Element_extend(ElementObject *self, PyObject *elements)
|
|||
/*[clinic end generated code: output=f6e67fc2ff529191 input=807bc4f31c69f7c0]*/
|
||||
{
|
||||
PyObject* seq;
|
||||
Py_ssize_t i, seqlen = 0;
|
||||
Py_ssize_t i;
|
||||
|
||||
seq = PySequence_Fast(elements, "");
|
||||
if (!seq) {
|
||||
|
|
@ -1105,22 +1105,25 @@ _elementtree_Element_extend(ElementObject *self, PyObject *elements)
|
|||
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 (!PyObject_IsInstance(element, (PyObject *)&Element_Type)) {
|
||||
Py_DECREF(seq);
|
||||
Py_INCREF(element);
|
||||
if (!PyObject_TypeCheck(element, (PyTypeObject *)&Element_Type)) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"expected an Element, not \"%.200s\"",
|
||||
Py_TYPE(element)->tp_name);
|
||||
Py_DECREF(seq);
|
||||
Py_DECREF(element);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (element_add_subelement(self, element) < 0) {
|
||||
Py_DECREF(seq);
|
||||
Py_DECREF(element);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(element);
|
||||
}
|
||||
|
||||
Py_DECREF(seq);
|
||||
|
|
@ -1156,11 +1159,16 @@ _elementtree_Element_find_impl(ElementObject *self, PyObject *path,
|
|||
|
||||
for (i = 0; i < self->extra->length; i++) {
|
||||
PyObject* item = self->extra->children[i];
|
||||
if (Element_CheckExact(item) &&
|
||||
PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ) == 1) {
|
||||
Py_INCREF(item);
|
||||
int rc;
|
||||
if (!Element_CheckExact(item))
|
||||
continue;
|
||||
Py_INCREF(item);
|
||||
rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ);
|
||||
if (rc > 0)
|
||||
return item;
|
||||
}
|
||||
Py_DECREF(item);
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
|
|
@ -1197,14 +1205,24 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyObject *path,
|
|||
|
||||
for (i = 0; i < self->extra->length; i++) {
|
||||
ElementObject* item = (ElementObject*) self->extra->children[i];
|
||||
if (Element_CheckExact(item) &&
|
||||
(PyObject_RichCompareBool(item->tag, path, Py_EQ) == 1)) {
|
||||
int rc;
|
||||
if (!Element_CheckExact(item))
|
||||
continue;
|
||||
Py_INCREF(item);
|
||||
rc = PyObject_RichCompareBool(item->tag, path, Py_EQ);
|
||||
if (rc > 0) {
|
||||
PyObject* text = element_get_text(item);
|
||||
if (text == Py_None)
|
||||
if (text == Py_None) {
|
||||
Py_DECREF(item);
|
||||
return PyUnicode_New(0, 0);
|
||||
}
|
||||
Py_XINCREF(text);
|
||||
Py_DECREF(item);
|
||||
return text;
|
||||
}
|
||||
Py_DECREF(item);
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(default_value);
|
||||
|
|
@ -1245,13 +1263,17 @@ _elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
|
|||
|
||||
for (i = 0; i < self->extra->length; i++) {
|
||||
PyObject* item = self->extra->children[i];
|
||||
if (Element_CheckExact(item) &&
|
||||
PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) {
|
||||
if (PyList_Append(out, item) < 0) {
|
||||
Py_DECREF(out);
|
||||
return NULL;
|
||||
}
|
||||
int rc;
|
||||
if (!Element_CheckExact(item))
|
||||
continue;
|
||||
Py_INCREF(item);
|
||||
rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ);
|
||||
if (rc != 0 && (rc < 0 || PyList_Append(out, item) < 0)) {
|
||||
Py_DECREF(item);
|
||||
Py_DECREF(out);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(item);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
|
@ -1507,6 +1529,8 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement)
|
|||
/*[clinic end generated code: output=38fe6c07d6d87d1f input=d52fc28ededc0bd8]*/
|
||||
{
|
||||
Py_ssize_t i;
|
||||
int rc;
|
||||
PyObject *found;
|
||||
|
||||
if (!self->extra) {
|
||||
/* element has no children, so raise exception */
|
||||
|
|
@ -1520,11 +1544,14 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement)
|
|||
for (i = 0; i < self->extra->length; i++) {
|
||||
if (self->extra->children[i] == subelement)
|
||||
break;
|
||||
if (PyObject_RichCompareBool(self->extra->children[i], subelement, Py_EQ) == 1)
|
||||
rc = PyObject_RichCompareBool(self->extra->children[i], subelement, Py_EQ);
|
||||
if (rc > 0)
|
||||
break;
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (i == self->extra->length) {
|
||||
if (i >= self->extra->length) {
|
||||
/* subelement is not in children, so raise exception */
|
||||
PyErr_SetString(
|
||||
PyExc_ValueError,
|
||||
|
|
@ -1533,13 +1560,13 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2033,6 +2060,7 @@ elementiter_next(ElementIterObject *it)
|
|||
*/
|
||||
ElementObject *cur_parent;
|
||||
Py_ssize_t child_index;
|
||||
int rc;
|
||||
|
||||
while (1) {
|
||||
/* Handle the case reached in the beginning and end of iteration, where
|
||||
|
|
@ -2054,14 +2082,22 @@ elementiter_next(ElementIterObject *it)
|
|||
}
|
||||
|
||||
it->root_done = 1;
|
||||
if (it->sought_tag == Py_None ||
|
||||
PyObject_RichCompareBool(it->root_element->tag,
|
||||
it->sought_tag, Py_EQ) == 1) {
|
||||
rc = (it->sought_tag == Py_None);
|
||||
if (!rc) {
|
||||
rc = PyObject_RichCompareBool(it->root_element->tag,
|
||||
it->sought_tag, Py_EQ);
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
}
|
||||
if (rc) {
|
||||
if (it->gettext) {
|
||||
PyObject *text = element_get_text(it->root_element);
|
||||
if (!text)
|
||||
return NULL;
|
||||
if (PyObject_IsTrue(text)) {
|
||||
rc = PyObject_IsTrue(text);
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
if (rc) {
|
||||
Py_INCREF(text);
|
||||
return text;
|
||||
}
|
||||
|
|
@ -2093,18 +2129,26 @@ elementiter_next(ElementIterObject *it)
|
|||
PyObject *text = element_get_text(child);
|
||||
if (!text)
|
||||
return NULL;
|
||||
if (PyObject_IsTrue(text)) {
|
||||
rc = PyObject_IsTrue(text);
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
if (rc) {
|
||||
Py_INCREF(text);
|
||||
return text;
|
||||
}
|
||||
} else if (it->sought_tag == Py_None ||
|
||||
PyObject_RichCompareBool(child->tag,
|
||||
it->sought_tag, Py_EQ) == 1) {
|
||||
Py_INCREF(child);
|
||||
return (PyObject *)child;
|
||||
} else {
|
||||
rc = (it->sought_tag == Py_None);
|
||||
if (!rc) {
|
||||
rc = PyObject_RichCompareBool(child->tag,
|
||||
it->sought_tag, Py_EQ);
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
}
|
||||
if (rc) {
|
||||
Py_INCREF(child);
|
||||
return (PyObject *)child;
|
||||
}
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
PyObject *tail;
|
||||
|
|
@ -2124,9 +2168,14 @@ elementiter_next(ElementIterObject *it)
|
|||
* this is because itertext() is supposed to only return *inner*
|
||||
* text, not text following the element it began iteration with.
|
||||
*/
|
||||
if (it->parent_stack->parent && PyObject_IsTrue(tail)) {
|
||||
Py_INCREF(tail);
|
||||
return tail;
|
||||
if (it->parent_stack->parent) {
|
||||
rc = PyObject_IsTrue(tail);
|
||||
if (rc < 0)
|
||||
return NULL;
|
||||
if (rc) {
|
||||
Py_INCREF(tail);
|
||||
return tail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2184,20 +2233,21 @@ static PyObject *
|
|||
create_elementiter(ElementObject *self, PyObject *tag, int gettext)
|
||||
{
|
||||
ElementIterObject *it;
|
||||
PyObject *star = NULL;
|
||||
|
||||
it = PyObject_GC_New(ElementIterObject, &ElementIter_Type);
|
||||
if (!it)
|
||||
return NULL;
|
||||
|
||||
if (PyUnicode_Check(tag))
|
||||
star = PyUnicode_FromString("*");
|
||||
else if (PyBytes_Check(tag))
|
||||
star = PyBytes_FromString("*");
|
||||
|
||||
if (star && PyObject_RichCompareBool(tag, star, Py_EQ) == 1)
|
||||
tag = Py_None;
|
||||
Py_XDECREF(star);
|
||||
if (PyUnicode_Check(tag)) {
|
||||
if (PyUnicode_READY(tag) < 0)
|
||||
return NULL;
|
||||
if (PyUnicode_GET_LENGTH(tag) == 1 && PyUnicode_READ_CHAR(tag, 0) == '*')
|
||||
tag = Py_None;
|
||||
}
|
||||
else if (PyBytes_Check(tag)) {
|
||||
if (PyBytes_GET_SIZE(tag) == 1 && *PyBytes_AS_STRING(tag) == '*')
|
||||
tag = Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(tag);
|
||||
it->sought_tag = tag;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue