diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-05-05 08:11:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-05 08:11:55 (GMT) |
commit | d81f9e24ea89c0aaded1e0d3f8d8076bbd58c19a (patch) | |
tree | 16d3faf0c675d130d6a7163b53f4f87d4e7ac630 /Lib/xml | |
parent | fd6094cdebb5736745d164e0207de2d4cb0b50dc (diff) | |
download | cpython-d81f9e24ea89c0aaded1e0d3f8d8076bbd58c19a.zip cpython-d81f9e24ea89c0aaded1e0d3f8d8076bbd58c19a.tar.gz cpython-d81f9e24ea89c0aaded1e0d3f8d8076bbd58c19a.tar.bz2 |
bpo-30264: ExpatParser now closes the source (#1476)
ExpatParser.parse() of xml.sax.xmlreader now closes the source: close
the file object or the urllib object if source is a string (not an
open file-like object).
Add test_parse_close_source() unit test.
Diffstat (limited to 'Lib/xml')
-rw-r--r-- | Lib/xml/sax/expatreader.py | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py index 21c9db9..bae663b 100644 --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -105,9 +105,16 @@ class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator): source = saxutils.prepare_input_source(source) self._source = source - self.reset() - self._cont_handler.setDocumentLocator(ExpatLocator(self)) - xmlreader.IncrementalParser.parse(self, source) + try: + self.reset() + self._cont_handler.setDocumentLocator(ExpatLocator(self)) + xmlreader.IncrementalParser.parse(self, source) + except: + # bpo-30264: Close the source on error to not leak resources: + # xml.sax.parse() doesn't give access to the underlying parser + # to the caller + self._close_source() + raise def prepareParser(self, source): if source.getSystemId() is not None: @@ -216,6 +223,17 @@ class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator): # FIXME: when to invoke error()? self._err_handler.fatalError(exc) + def _close_source(self): + source = self._source + try: + file = source.getCharacterStream() + if file is not None: + file.close() + finally: + file = source.getByteStream() + if file is not None: + file.close() + def close(self): if (self._entity_stack or self._parser is None or isinstance(self._parser, _ClosedParser)): @@ -235,6 +253,7 @@ class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator): parser.ErrorColumnNumber = self._parser.ErrorColumnNumber parser.ErrorLineNumber = self._parser.ErrorLineNumber self._parser = parser + self._close_source() def _reset_cont_handler(self): self._parser.ProcessingInstructionHandler = \ |