bpo-27863: Fixed multiple crashes in ElementTree. (#765) (#904)

(cherry picked from commit 576def096e)
This commit is contained in:
Serhiy Storchaka 2017-03-30 10:32:19 +03:00 committed by GitHub
parent 0fadf25e69
commit c90ff1b78c
3 changed files with 167 additions and 48 deletions

View file

@ -155,7 +155,7 @@ deepcopy(PyObject* object, PyObject* memo)
LOCAL(PyObject*)
list_join(PyObject* list)
{
/* join list elements (destroying the list in the process) */
/* join list elements */
PyObject* joiner;
PyObject* result;
@ -164,8 +164,6 @@ list_join(PyObject* list)
return NULL;
result = PyUnicode_Join(joiner, list);
Py_DECREF(joiner);
if (result)
Py_DECREF(list);
return result;
}
@ -534,15 +532,17 @@ element_get_text(ElementObject* self)
{
/* return borrowed reference to text attribute */
PyObject* res = self->text;
PyObject *res = self->text;
if (JOIN_GET(res)) {
res = JOIN_OBJ(res);
if (PyList_CheckExact(res)) {
res = list_join(res);
if (!res)
PyObject *tmp = list_join(res);
if (!tmp)
return NULL;
self->text = res;
self->text = tmp;
Py_DECREF(res);
res = tmp;
}
}
@ -554,15 +554,17 @@ element_get_tail(ElementObject* self)
{
/* return borrowed reference to text attribute */
PyObject* res = self->tail;
PyObject *res = self->tail;
if (JOIN_GET(res)) {
res = JOIN_OBJ(res);
if (PyList_CheckExact(res)) {
res = list_join(res);
if (!res)
PyObject *tmp = list_join(res);
if (!tmp)
return NULL;
self->tail = res;
self->tail = tmp;
Py_DECREF(res);
res = tmp;
}
}
@ -2147,6 +2149,12 @@ elementiter_next(ElementIterObject *it)
cur_parent = it->parent_stack->parent;
child_index = it->parent_stack->child_index;
if (cur_parent->extra && child_index < cur_parent->extra->length) {
if (!PyObject_TypeCheck(cur_parent->extra->children[child_index], &Element_Type)) {
PyErr_Format(PyExc_AttributeError,
"'%.100s' object has no attribute 'iter'",
Py_TYPE(cur_parent->extra->children[child_index])->tp_name);
return NULL;
}
elem = (ElementObject *)cur_parent->extra->children[child_index];
it->parent_stack->child_index++;
it->parent_stack = parent_stack_push_new(it->parent_stack,
@ -2435,40 +2443,51 @@ treebuilder_dealloc(TreeBuilderObject *self)
/* helpers for handling of arbitrary element-like objects */
static int
treebuilder_set_element_text_or_tail(PyObject *element, PyObject *data,
treebuilder_set_element_text_or_tail(PyObject *element, PyObject **data,
PyObject **dest, _Py_Identifier *name)
{
if (Element_CheckExact(element)) {
Py_DECREF(JOIN_OBJ(*dest));
*dest = JOIN_SET(data, PyList_CheckExact(data));
PyObject *tmp = JOIN_OBJ(*dest);
*dest = JOIN_SET(*data, PyList_CheckExact(*data));
*data = NULL;
Py_DECREF(tmp);
return 0;
}
else {
PyObject *joined = list_join(data);
PyObject *joined = list_join(*data);
int r;
if (joined == NULL)
return -1;
r = _PyObject_SetAttrId(element, name, joined);
Py_DECREF(joined);
return r;
if (r < 0)
return -1;
Py_CLEAR(*data);
return 0;
}
}
/* These two functions steal a reference to data */
static int
treebuilder_set_element_text(PyObject *element, PyObject *data)
LOCAL(int)
treebuilder_flush_data(TreeBuilderObject* self)
{
_Py_IDENTIFIER(text);
return treebuilder_set_element_text_or_tail(
element, data, &((ElementObject *) element)->text, &PyId_text);
}
PyObject *element = self->last;
static int
treebuilder_set_element_tail(PyObject *element, PyObject *data)
{
_Py_IDENTIFIER(tail);
return treebuilder_set_element_text_or_tail(
element, data, &((ElementObject *) element)->tail, &PyId_tail);
if (!self->data) {
return 0;
}
if (self->this == element) {
_Py_IDENTIFIER(text);
return treebuilder_set_element_text_or_tail(
element, &self->data,
&((ElementObject *) element)->text, &PyId_text);
}
else {
_Py_IDENTIFIER(tail);
return treebuilder_set_element_text_or_tail(
element, &self->data,
&((ElementObject *) element)->tail, &PyId_tail);
}
}
static int
@ -2517,16 +2536,8 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
PyObject* this;
elementtreestate *st = ET_STATE_GLOBAL;
if (self->data) {
if (self->this == self->last) {
if (treebuilder_set_element_text(self->last, self->data))
return NULL;
}
else {
if (treebuilder_set_element_tail(self->last, self->data))
return NULL;
}
self->data = NULL;
if (treebuilder_flush_data(self) < 0) {
return NULL;
}
if (self->element_factory && self->element_factory != Py_None) {
@ -2622,15 +2633,8 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
{
PyObject* item;
if (self->data) {
if (self->this == self->last) {
if (treebuilder_set_element_text(self->last, self->data))
return NULL;
} else {
if (treebuilder_set_element_tail(self->last, self->data))
return NULL;
}
self->data = NULL;
if (treebuilder_flush_data(self) < 0) {
return NULL;
}
if (self->index == 0) {