Skip to content

Commit 096e41a

Browse files
[3.7] bpo-31758: Prevent crashes when using an uninitialized _elementtree.XMLParser object (GH-3997) (GH-19487)
(cherry picked from commit 402e1cd)
1 parent 4057e8f commit 096e41a

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

Lib/test/test_xml_etree_c.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,23 @@ def __del__(self):
118118
elem.tail = X()
119119
elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure
120120

121+
@support.cpython_only
122+
def test_uninitialized_parser(self):
123+
# The interpreter shouldn't crash in case of calling methods or
124+
# accessing attributes of uninitialized XMLParser objects.
125+
parser = cET.XMLParser.__new__(cET.XMLParser)
126+
self.assertRaises(ValueError, parser.close)
127+
self.assertRaises(ValueError, parser.feed, 'foo')
128+
class MockFile:
129+
def read(*args):
130+
return ''
131+
self.assertRaises(ValueError, parser._parse_whole, MockFile())
132+
self.assertRaises(ValueError, parser._setevents, None)
133+
with self.assertRaises(ValueError):
134+
parser.entity
135+
with self.assertRaises(ValueError):
136+
parser.target
137+
121138
def test_setstate_leaks(self):
122139
# Test reference leaks
123140
elem = cET.Element.__new__(cET.Element)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Prevent crashes when using an uninitialized ``_elementtree.XMLParser``
2+
object. Patch by Oren Milman.

Modules/_elementtree.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3474,6 +3474,17 @@ xmlparser_dealloc(XMLParserObject* self)
34743474
Py_TYPE(self)->tp_free((PyObject *)self);
34753475
}
34763476

3477+
Py_LOCAL_INLINE(int)
3478+
_check_xmlparser(XMLParserObject* self)
3479+
{
3480+
if (self->target == NULL) {
3481+
PyErr_SetString(PyExc_ValueError,
3482+
"XMLParser.__init__() wasn't called");
3483+
return 0;
3484+
}
3485+
return 1;
3486+
}
3487+
34773488
LOCAL(PyObject*)
34783489
expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
34793490
{
@@ -3510,6 +3521,10 @@ _elementtree_XMLParser_close_impl(XMLParserObject *self)
35103521
/* end feeding data to parser */
35113522

35123523
PyObject* res;
3524+
3525+
if (!_check_xmlparser(self)) {
3526+
return NULL;
3527+
}
35133528
res = expat_parse(self, "", 0, 1);
35143529
if (!res)
35153530
return NULL;
@@ -3541,6 +3556,9 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
35413556
{
35423557
/* feed data to parser */
35433558

3559+
if (!_check_xmlparser(self)) {
3560+
return NULL;
3561+
}
35443562
if (PyUnicode_Check(data)) {
35453563
Py_ssize_t data_len;
35463564
const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len);
@@ -3588,6 +3606,9 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
35883606
PyObject* temp;
35893607
PyObject* res;
35903608

3609+
if (!_check_xmlparser(self)) {
3610+
return NULL;
3611+
}
35913612
reader = PyObject_GetAttrString(file, "read");
35923613
if (!reader)
35933614
return NULL;
@@ -3699,6 +3720,9 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
36993720
TreeBuilderObject *target;
37003721
PyObject *events_append, *events_seq;
37013722

3723+
if (!_check_xmlparser(self)) {
3724+
return NULL;
3725+
}
37023726
if (!TreeBuilder_CheckExact(self->target)) {
37033727
PyErr_SetString(
37043728
PyExc_TypeError,
@@ -3794,6 +3818,9 @@ xmlparser_getattro(XMLParserObject* self, PyObject* nameobj)
37943818
else
37953819
goto generic;
37963820

3821+
if (!res && !_check_xmlparser(self)) {
3822+
return NULL;
3823+
}
37973824
Py_INCREF(res);
37983825
return res;
37993826
}

0 commit comments

Comments
 (0)