-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
multiple issues in _elementtree module #72050
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'll describe 7 issues in the /Modules/_elementtree.c module here. They Issue 1: use-after-free in element_get_text The problematic code looks like this:
PyObject* res = self->text;
if (JOIN_GET(res)) {
res = JOIN_OBJ(res);
if (PyList_CheckExact(res)) {
res = list_join(res);
if (!res)
return NULL;
self->text = res;
}
}
return res;
} As we can see, if res is a list, we call list_join with res, which is PoC (Proof-of-Concept segfaulting script): --- import _elementtree as et
class X(str):
def __del__(self):
print(elem.text)
b = et.TreeBuilder()
b.start("test")
b.data(["AAAA", X("BBBB")])
b.start("test2")
elem = b.close()
print(elem.text) Issue 2: use-after-free in element_get_tail The same type of issue also exists in element_get_tail and should be fixed Issue 3: type confusion in elementiter_next The function elementiter_next iterates over a tree consisting of elements. Before doing any casts, most of the elementtree code is careful to check that
If the child is not an element, a type confusion occurs. Here's a PoC: ----- import _elementtree as et
state = {
"tag": "tag",
"_children": [1,2,3],
"attrib": "attr",
"tail": "tail",
"text": "text",
}
e = et.Element("ttt")
e.__setstate__(state)
for x in e.iter():
print(x) Issue 4: array-out-of-bounds indexing in element_subscr This issue occurs when taking the subscript of an element. This is done using if (PySlice_GetIndicesEx(item,
self->extra->length,
&start, &stop, &step, &slicelen) < 0) {
return NULL;
} The problem is that to evaluate the indices, PySlice_GetIndicesEx might call The code then uses these variables for array indexing:
But this could go out of bounds and interpret arbitrary memory as a PyObject. --- import _elementtree as et
class X:
def __index__(self):
e[:] = []
return 1
e = et.Element("elem")
for _ in range(10):
e.insert(0, et.Element("child")) print(e[0:10:X()]) --- Running it results in a segfault: (gdb) r ./poc14.py Program received signal SIGSEGV, Segmentation fault. As we can see, "v" is freed memory with arbitrary contents. Issue 5: array-out-of-bounds indexing in element_ass_subscr A separate issue of the same type, also due to a call to PySlice_GetIndicesEx, --- import _elementtree as et
class X:
def __index__(self):
e[:] = []
return 1
e = et.Element("elem")
for _ in range(10):
e.insert(0, et.Element("child")) e[0:10:X()] = [] --- To fix these, I believe we could check whether self->extra->length changed Issue 6: use-after-free in treebuilder_handle_start In the function treebuilder_handle_start we see these lines:
Here self->last is the most recent element, and we are setting its text to PyObject *joined = list_join(data);
int r;
if (joined == NULL)
return -1;
r = _PyObject_SetAttrId(element, name, joined);
Py_DECREF(joined);
return r; The comment for list_join says this:
So note that we destroy the given list. If we go back to the initial function, Unfortunately the call to _PyObject_SetAttrId could fail -- for example if Here's a PoC: --- import _elementtree as et
b = et.TreeBuilder(element_factory=lambda x, y: 123)
b.start("tag", {})
b.data("ABCD")
b.start("tag2", {}) It sets self->last to be an integer, 123. When we try to set the attribute (gdb) run ./poc16.py
Traceback (most recent call last):
File "./poc16.py", line 7, in <module>
b.start("tag2", {})
AttributeError: 'int' object has no attribute 'text' Program received signal SIGSEGV, Segmentation fault. Note that this issue exists in two places inside treebuilder_handle_start -- the Issue 7: use-after-free in treebuilder_handle_end The same sort of issue also exists in treebuilder_handle_end and should be All these issues were found in Python-3.5.2 and tested with --with-pydebug |
Thank you for your report tehybel. |
Since it is hard to backport the bugfix to 2.7 without test, bpo-15083 is a dependence. |
Merge |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: