diff --git a/ansible_collections/netapp/ontap/plugins/module_utils/netapp.py b/ansible_collections/netapp/ontap/plugins/module_utils/netapp.py
index fcb3d9a4..8a577780 100644
--- a/ansible_collections/netapp/ontap/plugins/module_utils/netapp.py
+++ b/ansible_collections/netapp/ontap/plugins/module_utils/netapp.py
@@ -377,7 +377,13 @@ def _parse_response(self, response):
new_response = new_response.replace(b'\x07\r\n', b'')
# And 9.7 may send backspaces
for code_point in get_feature(self.module, 'sanitize_code_points'):
- new_response = new_response.replace(bytes([code_point]), b'.')
+ if bytes([8]) == b'\x08': # python 3
+ byte = bytes([code_point])
+ elif chr(8) == b'\x08': # python 2
+ byte = chr(code_point)
+ else: # very unlikely, noop
+ byte = b'.'
+ new_response = new_response.replace(byte, b'.')
try:
return super(OntapZAPICx, self)._parse_response(new_response)
except Exception:
diff --git a/ansible_collections/netapp/ontap/tests/unit/plugins/module_utils/test_netapp.py b/ansible_collections/netapp/ontap/tests/unit/plugins/module_utils/test_netapp.py
index 5c768400..f0d25206 100644
--- a/ansible_collections/netapp/ontap/tests/unit/plugins/module_utils/test_netapp.py
+++ b/ansible_collections/netapp/ontap/tests/unit/plugins/module_utils/test_netapp.py
@@ -136,8 +136,11 @@ def create_restapi_object(args):
return restApi
-def create_OntapZAPICx_object(args):
- module = create_module(args)
+def create_OntapZAPICx_object(args, feature_flags=None):
+ module_args = dict(args)
+ if feature_flags is not None:
+ module_args['feature_flags'] = feature_flags
+ module = create_module(module_args)
module.fail_json = fail_json
my_args = dict(args)
my_args.update(dict(module=module))
@@ -385,3 +388,47 @@ def test_classify_zapi_exception_other_error():
kind, new_message = netapp_utils.classify_zapi_exception(zapi_exception)
assert kind == 'other_error'
assert new_message == error_message
+
+
+def test_zapi_parse_response_sanitized():
+ ''' should not fail when trying to read invalid XML characters (\x08) '''
+ args = mock_args()
+ zapi_cx = create_OntapZAPICx_object(args)
+ response = b"\n\n"
+ response += b"\n"
+ response += b" (cluster log-forwarding create)\n\n"
+ response += b"Testing network connectivity to the destination host 10.10.10.10. \x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\n\n"
+ response += b"Error: command failed: Cannot contact destination host (10.10.10.10) from node\n"
+ response += b" "laurentn-vsim1". Verify connectivity to desired host or skip the\n"
+ response += b" connectivity check with the "-force" parameter."
+ response += b"0\n"
+ # Manually extract cli-output contents
+ cli_output = response.split(b'')[1]
+ cli_output = cli_output.split(b'')[0]
+ cli_output = cli_output.replace(b'"', b'"')
+ # the XML parser would chole on \x08, zapi_cx._parse_response replaces them with '.'
+ cli_output = cli_output.replace(b'\x08', b'.')
+ # Use xml parser to extract cli-output contents
+ xml = zapi_cx._parse_response(response)
+ results = xml.get_child_by_name('results')
+ new_cli_output = results.get_child_content('cli-output')
+ assert cli_output.decode() == new_cli_output
+
+
+def test_zapi_parse_response_unsanitized():
+ ''' should fail when trying to read invalid XML characters (\x08) '''
+ args = mock_args()
+ # use feature_flags to disable sanitization
+ zapi_cx = create_OntapZAPICx_object(args, dict(sanitize_xml=False))
+ response = b"\n\n"
+ response += b"\n"
+ response += b" (cluster log-forwarding create)\n\n"
+ response += b"Testing network connectivity to the destination host 10.10.10.10. \x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\n\n"
+ response += b"Error: command failed: Cannot contact destination host (10.10.10.10) from node\n"
+ response += b" "laurentn-vsim1". Verify connectivity to desired host or skip the\n"
+ response += b" connectivity check with the "-force" parameter."
+ response += b"0\n"
+ with pytest.raises(netapp_utils.zapi.etree.XMLSyntaxError) as exc:
+ zapi_cx._parse_response(response)
+ msg = 'PCDATA invalid Char value 8'
+ assert exc.value.msg.startswith(msg)