Kaydet (Commit) 8afd7ab1 authored tarafından Miss Islington (bot)'s avatar Miss Islington (bot) Kaydeden (comit) Victor Stinner

[3.6] bpo-31499, xml.etree: Fix xmlparser_gc_clear() crash (GH-3641) (#3645)

* bpo-31499, xml.etree: Fix xmlparser_gc_clear() crash

xml.etree: xmlparser_gc_clear() now sets self.parser to NULL to prevent a
crash in xmlparser_dealloc() if xmlparser_gc_clear() was called previously
by the garbage collector, because the parser was part of a reference cycle.
Co-Authored-By: 's avatarSerhiy Storchaka <storchaka@gmail.com>
(cherry picked from commit e727d41f)
üst 84c89ef4
......@@ -64,6 +64,26 @@ class MiscTests(unittest.TestCase):
del root
support.gc_collect()
def test_parser_ref_cycle(self):
# bpo-31499: xmlparser_dealloc() crashed with a segmentation fault when
# xmlparser_gc_clear() was called previously by the garbage collector,
# when the parser was part of a reference cycle.
def parser_ref_cycle():
parser = cET.XMLParser()
# Create a reference cycle using an exception to keep the frame
# alive, so the parser will be destroyed by the garbage collector
try:
raise ValueError
except ValueError as exc:
err = exc
# Create a parser part of reference cycle
parser_ref_cycle()
# Trigger an explicit garbage collection to break the reference cycle
# and so destroy the parser
support.gc_collect()
@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
......
xml.etree: Fix a crash when a parser is part of a reference cycle.
......@@ -3367,7 +3367,11 @@ xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
static int
xmlparser_gc_clear(XMLParserObject *self)
{
EXPAT(ParserFree)(self->parser);
if (self->parser != NULL) {
XML_Parser parser = self->parser;
self->parser = NULL;
EXPAT(ParserFree)(parser);
}
Py_CLEAR(self->handle_close);
Py_CLEAR(self->handle_pi);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment