Skip to content

Commit 6151148

Browse files
bpo-31758: Prevent crashes when using an uninitialized _elementtree.XMLParser object (GH-3997) (GH-19485)
(cherry picked from commit 402e1cd)
1 parent ee249d7 commit 6151148

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

Lib/test/test_xml_etree_c.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,21 @@ 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+
self.assertIsNone(parser.entity)
134+
self.assertIsNone(parser.target)
135+
121136
def test_setstate_leaks(self):
122137
# Test reference leaks
123138
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: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3877,6 +3877,17 @@ xmlparser_dealloc(XMLParserObject* self)
38773877
Py_TYPE(self)->tp_free((PyObject *)self);
38783878
}
38793879

3880+
Py_LOCAL_INLINE(int)
3881+
_check_xmlparser(XMLParserObject* self)
3882+
{
3883+
if (self->target == NULL) {
3884+
PyErr_SetString(PyExc_ValueError,
3885+
"XMLParser.__init__() wasn't called");
3886+
return 0;
3887+
}
3888+
return 1;
3889+
}
3890+
38803891
LOCAL(PyObject*)
38813892
expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
38823893
{
@@ -3913,6 +3924,10 @@ _elementtree_XMLParser_close_impl(XMLParserObject *self)
39133924
/* end feeding data to parser */
39143925

39153926
PyObject* res;
3927+
3928+
if (!_check_xmlparser(self)) {
3929+
return NULL;
3930+
}
39163931
res = expat_parse(self, "", 0, 1);
39173932
if (!res)
39183933
return NULL;
@@ -3944,6 +3959,9 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
39443959
{
39453960
/* feed data to parser */
39463961

3962+
if (!_check_xmlparser(self)) {
3963+
return NULL;
3964+
}
39473965
if (PyUnicode_Check(data)) {
39483966
Py_ssize_t data_len;
39493967
const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len);
@@ -3991,6 +4009,9 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
39914009
PyObject* temp;
39924010
PyObject* res;
39934011

4012+
if (!_check_xmlparser(self)) {
4013+
return NULL;
4014+
}
39944015
reader = PyObject_GetAttrString(file, "read");
39954016
if (!reader)
39964017
return NULL;
@@ -4078,6 +4099,9 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
40784099
TreeBuilderObject *target;
40794100
PyObject *events_append, *events_seq;
40804101

4102+
if (!_check_xmlparser(self)) {
4103+
return NULL;
4104+
}
40814105
if (!TreeBuilder_CheckExact(self->target)) {
40824106
PyErr_SetString(
40834107
PyExc_TypeError,

0 commit comments

Comments
 (0)