bpo-31758: Prevent crashes when using an uninitialized _elementtree.XMLParser object (GH-3997)

This commit is contained in:
Oren Milman 2020-04-12 17:36:41 +03:00 committed by GitHub
parent 63e5b59c06
commit 402e1cdb13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 0 deletions

View file

@ -115,6 +115,21 @@ class MiscTests(unittest.TestCase):
elem.tail = X() elem.tail = X()
elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure
@support.cpython_only
def test_uninitialized_parser(self):
# The interpreter shouldn't crash in case of calling methods or
# accessing attributes of uninitialized XMLParser objects.
parser = cET.XMLParser.__new__(cET.XMLParser)
self.assertRaises(ValueError, parser.close)
self.assertRaises(ValueError, parser.feed, 'foo')
class MockFile:
def read(*args):
return ''
self.assertRaises(ValueError, parser._parse_whole, MockFile())
self.assertRaises(ValueError, parser._setevents, None)
self.assertIsNone(parser.entity)
self.assertIsNone(parser.target)
def test_setstate_leaks(self): def test_setstate_leaks(self):
# Test reference leaks # Test reference leaks
elem = cET.Element.__new__(cET.Element) elem = cET.Element.__new__(cET.Element)

View file

@ -0,0 +1,2 @@
Prevent crashes when using an uninitialized ``_elementtree.XMLParser``
object. Patch by Oren Milman.

View file

@ -3818,6 +3818,17 @@ xmlparser_dealloc(XMLParserObject* self)
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }
Py_LOCAL_INLINE(int)
_check_xmlparser(XMLParserObject* self)
{
if (self->target == NULL) {
PyErr_SetString(PyExc_ValueError,
"XMLParser.__init__() wasn't called");
return 0;
}
return 1;
}
LOCAL(PyObject*) LOCAL(PyObject*)
expat_parse(XMLParserObject* self, const char* data, int data_len, int final) expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
{ {
@ -3854,6 +3865,10 @@ _elementtree_XMLParser_close_impl(XMLParserObject *self)
/* end feeding data to parser */ /* end feeding data to parser */
PyObject* res; PyObject* res;
if (!_check_xmlparser(self)) {
return NULL;
}
res = expat_parse(self, "", 0, 1); res = expat_parse(self, "", 0, 1);
if (!res) if (!res)
return NULL; return NULL;
@ -3885,6 +3900,9 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
{ {
/* feed data to parser */ /* feed data to parser */
if (!_check_xmlparser(self)) {
return NULL;
}
if (PyUnicode_Check(data)) { if (PyUnicode_Check(data)) {
Py_ssize_t data_len; Py_ssize_t data_len;
const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len); const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len);
@ -3932,6 +3950,9 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
PyObject* temp; PyObject* temp;
PyObject* res; PyObject* res;
if (!_check_xmlparser(self)) {
return NULL;
}
reader = PyObject_GetAttrString(file, "read"); reader = PyObject_GetAttrString(file, "read");
if (!reader) if (!reader)
return NULL; return NULL;
@ -4019,6 +4040,9 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
TreeBuilderObject *target; TreeBuilderObject *target;
PyObject *events_append, *events_seq; PyObject *events_append, *events_seq;
if (!_check_xmlparser(self)) {
return NULL;
}
if (!TreeBuilder_CheckExact(self->target)) { if (!TreeBuilder_CheckExact(self->target)) {
PyErr_SetString( PyErr_SetString(
PyExc_TypeError, PyExc_TypeError,