Check for XML parsing errors and disconnect in that case.

This commit is contained in:
Emmanuel Gil Peyrot 2016-12-29 18:59:09 +01:00
parent df4012e66d
commit 6034df0a78

View File

@ -19,7 +19,7 @@ import ssl
import weakref import weakref
import uuid import uuid
import xml.etree.ElementTree import xml.etree.ElementTree as ET
from slixmpp.xmlstream.asyncio import asyncio from slixmpp.xmlstream.asyncio import asyncio
from slixmpp.xmlstream import tostring, highlight from slixmpp.xmlstream import tostring, highlight
@ -339,7 +339,7 @@ class XMLStream(asyncio.BaseProtocol):
""" """
self.xml_depth = 0 self.xml_depth = 0
self.xml_root = None self.xml_root = None
self.parser = xml.etree.ElementTree.XMLPullParser(("start", "end")) self.parser = ET.XMLPullParser(("start", "end"))
def connection_made(self, transport): def connection_made(self, transport):
"""Called when the TCP connection has been established with the server """Called when the TCP connection has been established with the server
@ -359,34 +359,46 @@ class XMLStream(asyncio.BaseProtocol):
the stream is opened, etc). the stream is opened, etc).
""" """
self.parser.feed(data) self.parser.feed(data)
for event, xml in self.parser.read_events(): try:
if event == 'start': for event, xml in self.parser.read_events():
if self.xml_depth == 0: if event == 'start':
# We have received the start of the root element. if self.xml_depth == 0:
self.xml_root = xml # We have received the start of the root element.
log.debug('RECV: %s', self.xml_root = xml
highlight(tostring(self.xml_root, log.debug('RECV: %s',
xmlns=self.default_ns, highlight(tostring(self.xml_root,
stream=self, xmlns=self.default_ns,
top_level=True, stream=self,
open_only=True))) top_level=True,
self.start_stream_handler(self.xml_root) open_only=True)))
self.xml_depth += 1 self.start_stream_handler(self.xml_root)
if event == 'end': self.xml_depth += 1
self.xml_depth -= 1 if event == 'end':
if self.xml_depth == 0: self.xml_depth -= 1
# The stream's root element has closed, if self.xml_depth == 0:
# terminating the stream. # The stream's root element has closed,
log.debug("End of stream received") # terminating the stream.
self.abort() log.debug("End of stream received")
elif self.xml_depth == 1: self.abort()
# A stanza is an XML element that is a direct child of elif self.xml_depth == 1:
# the root element, hence the check of depth == 1 # A stanza is an XML element that is a direct child of
self._spawn_event(xml) # the root element, hence the check of depth == 1
if self.xml_root is not None: self._spawn_event(xml)
# Keep the root element empty of children to if self.xml_root is not None:
# save on memory use. # Keep the root element empty of children to
self.xml_root.clear() # save on memory use.
self.xml_root.clear()
except ET.ParseError:
log.error('Parse error: %r', data)
# Due to cyclic dependencies, this cant be imported at the module
# level.
from slixmpp.stanza.stream_error import StreamError
error = StreamError()
error['condition'] = 'not-well-formed'
error['text'] = 'Server sent: %r' % data
self.send(error)
self.disconnect()
def is_connected(self): def is_connected(self):
return self.transport is not None return self.transport is not None