diff --git a/odoo/addons/base/models/assetsbundle.py b/odoo/addons/base/models/assetsbundle.py index 55f23a4b9a4..86141a82a4c 100644 --- a/odoo/addons/base/models/assetsbundle.py +++ b/odoo/addons/base/models/assetsbundle.py @@ -898,8 +898,11 @@ class XMLAsset(WebAsset): except AssetError as e: return u"console.error(%s);" % json.dumps(to_text(e)) - parser = etree.XMLParser(ns_clean=True, recover=True, remove_comments=True) - root = etree.parse(io.BytesIO(content.encode('utf-8')), parser=parser).getroot() + parser = etree.XMLParser(ns_clean=True, remove_comments=True, resolve_entities=False) + try: + root = etree.fromstring(content.encode('utf-8'), parser=parser) + except etree.XMLSyntaxError as e: + return f'Invalid XML template: {self.url} \n {e.msg} ' if root.tag in ('templates', 'template'): return ''.join(etree.tostring(el, encoding='unicode') for el in root) return etree.tostring(root, encoding='unicode') diff --git a/odoo/addons/test_assetsbundle/__manifest__.py b/odoo/addons/test_assetsbundle/__manifest__.py index 1ab5561d25b..632291e2ef7 100644 --- a/odoo/addons/test_assetsbundle/__manifest__.py +++ b/odoo/addons/test_assetsbundle/__manifest__.py @@ -62,6 +62,9 @@ 'test_assetsbundle.lazy_test_component': [ 'test_assetsbundle/static/tests/lazy_test_component/**/*', ], + 'test_assetsbundle.broken_xml': [ + 'test_assetsbundle/static/invalid_src/xml/invalid_xml.xml', + ], }, 'license': 'LGPL-3', } diff --git a/odoo/addons/test_assetsbundle/static/invalid_src/xml/invalid_xml.xml b/odoo/addons/test_assetsbundle/static/invalid_src/xml/invalid_xml.xml new file mode 100644 index 00000000000..51408a14070 --- /dev/null +++ b/odoo/addons/test_assetsbundle/static/invalid_src/xml/invalid_xml.xml @@ -0,0 +1,6 @@ + + + + content + + diff --git a/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py b/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py index 64642924f14..754a71469bd 100644 --- a/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py +++ b/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py @@ -626,6 +626,24 @@ class TestJavascriptAssetsBundle(FileTouchable): """)) +class TestXMLAssetsBundle(FileTouchable): + + def _get_asset(self, bundle, rtl=False, debug_assets=False): + files, _ = self.env['ir.qweb']._get_asset_content(bundle) + return AssetsBundle(bundle, files, env=self.env, debug_assets=debug_assets, rtl=rtl) + + def test_01_broken_xml(self): + """ Checks that a bundle don't try hard to parse broken xml, and returns a comprehensive + error message. + """ + self.bundle = self._get_asset('test_assetsbundle.broken_xml') + + # there shouldn't be any test_assetsvundle.invalid_xml template. + # there should be an parsing_error template with the parsing error message. + self.assertEqual(self.bundle.xml(), + 'Invalid XML template: /test_assetsbundle/static/invalid_src/xml/invalid_xml.xml \n Opening and ending tag mismatch: SomeComponent line 4 and t, line 5, column 7 ', + "the parsing error should be shown") + @tagged('-at_install', 'post_install') class TestAssetsBundleInBrowser(HttpCase):