From 3b413b626e7b33e5219625092ea154b0b7ed1d87 Mon Sep 17 00:00:00 2001 From: Sasha Wood Date: Sun, 14 Aug 2022 17:36:15 -0400 Subject: [PATCH 1/2] Handle empty SOAP body as client error --- spyne/protocol/soap/soap11.py | 7 ++++++- spyne/test/protocol/test_soap11.py | 12 ++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/spyne/protocol/soap/soap11.py b/spyne/protocol/soap/soap11.py index 75e1add71..7bc702338 100644 --- a/spyne/protocol/soap/soap11.py +++ b/spyne/protocol/soap/soap11.py @@ -93,7 +93,12 @@ def _from_soap(in_envelope_xml, xmlids=None, **kwargs): def _parse_xml_string(xml_string, parser, charset=None): xml_string = iter(xml_string) - chunk = next(xml_string) + try: + chunk = next(xml_string) + except StopIteration: + logger_invalid.error("missing body") + raise Fault('Client.XMLSyntaxError', 'Missing body') + if isinstance(chunk, six.binary_type): string = b''.join(chain( (chunk,), xml_string )) else: diff --git a/spyne/test/protocol/test_soap11.py b/spyne/test/protocol/test_soap11.py index 93af58ae9..0a0fb29d6 100755 --- a/spyne/test/protocol/test_soap11.py +++ b/spyne/test/protocol/test_soap11.py @@ -244,6 +244,18 @@ def test_href(self): # quick and dirty test href reconstruction self.assertEqual(len(payload[0]), 2) + def test_empty_body(self): + # If the soap request has no body, then you get an empty iterable + # as the envelope string. + # This should be treated as a client error. + envelope_string = iter([]) + + with self.assertRaises(Fault) as cm: + _parse_xml_string(envelope_string, + etree.XMLParser(), 'utf8') + self.assertEqual(cm.exception.faultcode, 'Client.XMLSyntaxError') + self.assertEqual(cm.exception.faultstring, 'Missing body') + def test_namespaces(self): m = ComplexModel.produce( namespace="some_namespace", From ca3f8364817fc8cd5e3f011c9556c315b63505fb Mon Sep 17 00:00:00 2001 From: Sasha Wood Date: Sun, 14 Aug 2022 17:34:36 -0400 Subject: [PATCH 2/2] Handle bad encoding of SOAP body as client error --- spyne/protocol/soap/soap11.py | 6 +++++- spyne/test/protocol/test_soap11.py | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/spyne/protocol/soap/soap11.py b/spyne/protocol/soap/soap11.py index 7bc702338..0b2df0561 100644 --- a/spyne/protocol/soap/soap11.py +++ b/spyne/protocol/soap/soap11.py @@ -105,7 +105,11 @@ def _parse_xml_string(xml_string, parser, charset=None): string = ''.join(chain( (chunk,), xml_string )) if charset: - string = string.decode(charset) + try: + string = string.decode(charset) + except UnicodeDecodeError as e: + logger_invalid.error("%r in string %r", e, string) + raise Fault('Client.XMLSyntaxError', str(e)) try: try: diff --git a/spyne/test/protocol/test_soap11.py b/spyne/test/protocol/test_soap11.py index 0a0fb29d6..6564c7209 100755 --- a/spyne/test/protocol/test_soap11.py +++ b/spyne/test/protocol/test_soap11.py @@ -256,6 +256,29 @@ def test_empty_body(self): self.assertEqual(cm.exception.faultcode, 'Client.XMLSyntaxError') self.assertEqual(cm.exception.faultstring, 'Missing body') + def test_bad_encoding(self): + # Encode string with non-ascii characters as Latin-1, so that later + # when decoding as utf-8 you will get an decode error. + # This should result in a client error. + envelope_string = [''' + + + + + + + +'''.encode('latin-1')] + + with self.assertRaises(Fault) as cm: + _parse_xml_string(envelope_string, + etree.XMLParser(), 'utf8') + self.assertEqual(cm.exception.faultcode, 'Client.XMLSyntaxError') + self.assertIn("'utf-8' codec can't decode byte", + cm.exception.faultstring) + def test_namespaces(self): m = ComplexModel.produce( namespace="some_namespace",