Skip to content

Commit 402e1cd

Browse files
authored
bpo-31758: Prevent crashes when using an uninitialized _elementtree.XMLParser object (GH-3997)
1 parent 63e5b59 commit 402e1cd

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
@@ -115,6 +115,21 @@ def __del__(self):
115115
elem.tail = X()
116116
elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure
117117

118+
@support.cpython_only
119+
def test_uninitialized_parser(self):
120+
# The interpreter shouldn't crash in case of calling methods or
121+
# accessing attributes of uninitialized XMLParser objects.
122+
parser = cET.XMLParser.__new__(cET.XMLParser)
123+
self.assertRaises(ValueError, parser.close)
124+
self.assertRaises(ValueError, parser.feed, 'foo')
125+
class MockFile:
126+
def read(*args):
127+
return ''
128+
self.assertRaises(ValueError, parser._parse_whole, MockFile())
129+
self.assertRaises(ValueError, parser._setevents, None)
130+
self.assertIsNone(parser.entity)
131+
self.assertIsNone(parser.target)
132+
118133
def test_setstate_leaks(self):
119134
# Test reference leaks
120135
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
@@ -3818,6 +3818,17 @@ xmlparser_dealloc(XMLParserObject* self)
38183818
Py_TYPE(self)->tp_free((PyObject *)self);
38193819
}
38203820

3821+
Py_LOCAL_INLINE(int)
3822+
_check_xmlparser(XMLParserObject* self)
3823+
{
3824+
if (self->target == NULL) {
3825+
PyErr_SetString(PyExc_ValueError,
3826+
"XMLParser.__init__() wasn't called");
3827+
return 0;
3828+
}
3829+
return 1;
3830+
}
3831+
38213832
LOCAL(PyObject*)
38223833
expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
38233834
{
@@ -3854,6 +3865,10 @@ _elementtree_XMLParser_close_impl(XMLParserObject *self)
38543865
/* end feeding data to parser */
38553866

38563867
PyObject* res;
3868+
3869+
if (!_check_xmlparser(self)) {
3870+
return NULL;
3871+
}
38573872
res = expat_parse(self, "", 0, 1);
38583873
if (!res)
38593874
return NULL;
@@ -3885,6 +3900,9 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
38853900
{
38863901
/* feed data to parser */
38873902

3903+
if (!_check_xmlparser(self)) {
3904+
return NULL;
3905+
}
38883906
if (PyUnicode_Check(data)) {
38893907
Py_ssize_t data_len;
38903908
const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len);
@@ -3932,6 +3950,9 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
39323950
PyObject* temp;
39333951
PyObject* res;
39343952

3953+
if (!_check_xmlparser(self)) {
3954+
return NULL;
3955+
}
39353956
reader = PyObject_GetAttrString(file, "read");
39363957
if (!reader)
39373958
return NULL;
@@ -4019,6 +4040,9 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
40194040
TreeBuilderObject *target;
40204041
PyObject *events_append, *events_seq;
40214042

4043+
if (!_check_xmlparser(self)) {
4044+
return NULL;
4045+
}
40224046
if (!TreeBuilder_CheckExact(self->target)) {
40234047
PyErr_SetString(
40244048
PyExc_TypeError,

0 commit comments

Comments
 (0)