Skip to content

Commit 49caab4

Browse files
miss-islingtonserhiy-storchaka
authored andcommitted
[3.6] bpo-31455: Fix an assertion failure in ElementTree.XMLParser(). (GH-3545) (#3585)
* Avoid calling "PyObject_GetAttrString()" (and potentially executing user code) with a live exception set. * Ignore only AttributeError on attribute lookups in ElementTree.XMLParser() and propagate all other exceptions. (cherry picked from commit c8d8e15)
1 parent 1658ec0 commit 49caab4

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

Lib/test/test_xml_etree.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2476,6 +2476,31 @@ def close(self):
24762476
('html', '-//W3C//DTD XHTML 1.0 Transitional//EN',
24772477
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'))
24782478

2479+
def test_builder_lookup_errors(self):
2480+
class RaisingBuilder:
2481+
def __init__(self, raise_in=None, what=ValueError):
2482+
self.raise_in = raise_in
2483+
self.what = what
2484+
2485+
def __getattr__(self, name):
2486+
if name == self.raise_in:
2487+
raise self.what(self.raise_in)
2488+
def handle(*args):
2489+
pass
2490+
return handle
2491+
2492+
ET.XMLParser(target=RaisingBuilder())
2493+
# cET also checks for 'close' and 'doctype', PyET does it only at need
2494+
for event in ('start', 'data', 'end', 'comment', 'pi'):
2495+
with self.assertRaisesRegex(ValueError, event):
2496+
ET.XMLParser(target=RaisingBuilder(event))
2497+
2498+
ET.XMLParser(target=RaisingBuilder(what=AttributeError))
2499+
for event in ('start', 'data', 'end', 'comment', 'pi'):
2500+
parser = ET.XMLParser(target=RaisingBuilder(event, what=AttributeError))
2501+
parser.feed(self.sample1)
2502+
self.assertIsNone(parser.close())
2503+
24792504

24802505
class XMLParserTest(unittest.TestCase):
24812506
sample1 = b'<file><line>22</line></file>'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The C accelerator module of ElementTree ignored exceptions raised when
2+
looking up TreeBuilder target methods in XMLParser().

Modules/_elementtree.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,6 +3224,18 @@ xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
32243224
return (PyObject *)self;
32253225
}
32263226

3227+
static int
3228+
ignore_attribute_error(PyObject *value)
3229+
{
3230+
if (value == NULL) {
3231+
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
3232+
return -1;
3233+
}
3234+
PyErr_Clear();
3235+
}
3236+
return 0;
3237+
}
3238+
32273239
/*[clinic input]
32283240
_elementtree.XMLParser.__init__
32293241
@@ -3270,14 +3282,33 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *html,
32703282
self->target = target;
32713283

32723284
self->handle_start = PyObject_GetAttrString(target, "start");
3285+
if (ignore_attribute_error(self->handle_start)) {
3286+
return -1;
3287+
}
32733288
self->handle_data = PyObject_GetAttrString(target, "data");
3289+
if (ignore_attribute_error(self->handle_data)) {
3290+
return -1;
3291+
}
32743292
self->handle_end = PyObject_GetAttrString(target, "end");
3293+
if (ignore_attribute_error(self->handle_end)) {
3294+
return -1;
3295+
}
32753296
self->handle_comment = PyObject_GetAttrString(target, "comment");
3297+
if (ignore_attribute_error(self->handle_comment)) {
3298+
return -1;
3299+
}
32763300
self->handle_pi = PyObject_GetAttrString(target, "pi");
3301+
if (ignore_attribute_error(self->handle_pi)) {
3302+
return -1;
3303+
}
32773304
self->handle_close = PyObject_GetAttrString(target, "close");
3305+
if (ignore_attribute_error(self->handle_close)) {
3306+
return -1;
3307+
}
32783308
self->handle_doctype = PyObject_GetAttrString(target, "doctype");
3279-
3280-
PyErr_Clear();
3309+
if (ignore_attribute_error(self->handle_doctype)) {
3310+
return -1;
3311+
}
32813312

32823313
/* configure parser */
32833314
EXPAT(SetUserData)(self->parser, self);

0 commit comments

Comments
 (0)