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

Oren Milman webhook-mailer at python.org
Sun Apr 12 10:36:49 EDT 2020


https://github.com/python/cpython/commit/402e1cdb132f384e4dcde7a3d7ec7ea1fc7ab527
commit: 402e1cdb132f384e4dcde7a3d7ec7ea1fc7ab527
branch: master
author: Oren Milman <orenmn at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-04-12T16:36:41+02:00
summary:

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

files:
A Misc/NEWS.d/next/Library/2017-10-14-21-02-40.bpo-31758.563ZZb.rst
M Lib/test/test_xml_etree_c.py
M Modules/_elementtree.c

diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index 15496fdba2ff8..7437e13d0611c 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -115,6 +115,21 @@ def __del__(self):
         elem.tail = X()
         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):
         # Test reference leaks
         elem = cET.Element.__new__(cET.Element)
diff --git a/Misc/NEWS.d/next/Library/2017-10-14-21-02-40.bpo-31758.563ZZb.rst b/Misc/NEWS.d/next/Library/2017-10-14-21-02-40.bpo-31758.563ZZb.rst
new file mode 100644
index 0000000000000..92e55db2b0986
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-10-14-21-02-40.bpo-31758.563ZZb.rst
@@ -0,0 +1,2 @@
+Prevent crashes when using an uninitialized ``_elementtree.XMLParser``
+object. Patch by Oren Milman.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 10d78dd58f011..03ac6b6c0743d 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -3818,6 +3818,17 @@ xmlparser_dealloc(XMLParserObject* 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*)
 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 */
 
     PyObject* res;
+
+    if (!_check_xmlparser(self)) {
+        return NULL;
+    }
     res = expat_parse(self, "", 0, 1);
     if (!res)
         return NULL;
@@ -3885,6 +3900,9 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
 {
     /* feed data to parser */
 
+    if (!_check_xmlparser(self)) {
+        return NULL;
+    }
     if (PyUnicode_Check(data)) {
         Py_ssize_t 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* res;
 
+    if (!_check_xmlparser(self)) {
+        return NULL;
+    }
     reader = PyObject_GetAttrString(file, "read");
     if (!reader)
         return NULL;
@@ -4019,6 +4040,9 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
     TreeBuilderObject *target;
     PyObject *events_append, *events_seq;
 
+    if (!_check_xmlparser(self)) {
+        return NULL;
+    }
     if (!TreeBuilder_CheckExact(self->target)) {
         PyErr_SetString(
             PyExc_TypeError,



More information about the Python-checkins mailing list