Use a per-thread XML parser instance

This commit is contained in:
Kovid Goyal 2019-12-29 18:24:56 +05:30
parent d102aca175
commit e5d6a6ef9f
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -6,14 +6,29 @@ from __future__ import absolute_import, division, print_function, unicode_litera
from lxml import etree
import threading
# resolve_entities is turned off as entities can cause
# reads of local files, for example:
# <!DOCTYPE foo [ <!ENTITY passwd SYSTEM "file:///etc/passwd" >]>
SAFE_XML_PARSER = etree.XMLParser(recover=True, no_network=True, resolve_entities=False)
SAFE_XML_PARSER_NO_RECOVER = etree.XMLParser(recover=False, no_network=True, resolve_entities=False)
class GlobalParserTLS(threading.local):
def __call__(self, recover):
parsers = getattr(self, 'parsers', None)
if parsers is None:
self.parsers = parsers = {
True: etree.XMLParser(recover=True, no_network=True, resolve_entities=False),
False: etree.XMLParser(recover=False, no_network=True, resolve_entities=False)
}
return parsers[recover]
_global_tls = GlobalParserTLS()
fs = etree.fromstring
def safe_xml_fromstring(string_or_bytes, recover=True):
return fs(string_or_bytes, SAFE_XML_PARSER if recover else SAFE_XML_PARSER_NO_RECOVER)
return fs(string_or_bytes, _global_tls(recover))