summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrangé <berrange@redhat.com>2022-03-25 11:44:52 +0000
committerDaniel P. Berrangé <berrange@redhat.com>2022-04-21 15:00:29 +0000
commit6feb31a7a10267e14183495915b191ecdf4ea3e8 (patch)
treefd24148856bf77ddb93253d5b69dcf8938354b28
parent3551c04ecb34540810a6cca629eb94b257b02db3 (diff)
downloadlibvirt-python-6feb31a7a10267e14183495915b191ecdf4ea3e8.tar.gz
sanitytest: skip tests when seeing broken lxml implementation
The python lxml registers some global callbacks with libxml2. As a result when another user of libxml2 calls APIs, it can trigger the python callbacks that lxml previously registered. Execution of the python callbacks in this case is often unsafe and leads to SEGVs. This hasn't been a problem since the sanitytest.py test has been a standalone program we execute. When it gets turned into a real python unit test, it will run in the same process as all the other tests and trigger the crash. A mitigation was added in lxml 4.5.2 which is good enough to let us continuing using lxml. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
-rw-r--r--sanitytest.py40
1 files changed, 38 insertions, 2 deletions
diff --git a/sanitytest.py b/sanitytest.py
index f3f925c..8f02cdf 100644
--- a/sanitytest.py
+++ b/sanitytest.py
@@ -1,8 +1,6 @@
#!/usr/bin/env python3
import sys
-import lxml
-import lxml.etree
from typing import Dict, List, Set, Tuple # noqa F401
import libvirt
import unittest
@@ -373,17 +371,55 @@ def validate_c_api_bindings_present(finalklassmap):
except AttributeError:
raise Exception("libvirt.libvirtmod.%s (C binding does not exist)" % pyname)
+# Historically python lxml is incompatible with any other
+# use of libxml2 in the same process. Merely importing
+# 'lxml.etree' will result in libvirt's use of libxml2
+# triggering a SEGV:
+#
+# https://bugs.launchpad.net/lxml/+bug/1748019
+#
+# per the last comment though, it was somewhat improved by
+#
+# https://github.com/lxml/lxml/commit/fa1d856cad369d0ac64323ddec14b02281491706
+#
+# so if we have version >= 4.5.2, we are safe to import
+# lxml.etree for the purposes of unit tests at least
+def broken_lxml():
+ import lxml
+
+ if not hasattr(lxml, "__version__"):
+ return True
+
+ digits = [int(d) for d in lxml.__version__.split(".")]
+
+ # We have 3 digits in versions today, but be paranoid
+ # for possible future changes.
+ if len(digits) != 3:
+ return False
+
+ version = (digits[0] * 1000 * 1000) + (digits[1] * 1000) + digits[2]
+ if version < 4005002:
+ return True
+
+ return False
api_test_flag = unittest.skipUnless(
os.environ.get('LIBVIRT_API_COVERAGE', False),
"API coverage test is only for upstream maintainers",
)
+lxml_broken_flag = unittest.skipIf(
+ broken_lxml(),
+ "lxml version clashes with libxml usage from libvirt"
+)
+
@api_test_flag
+@lxml_broken_flag
class LibvirtAPICoverage(unittest.TestCase):
def test_libvirt_api(self):
xml = get_libvirt_api_xml_path()
+ import lxml.etree
with open(xml, "r") as fp:
tree = lxml.etree.parse(fp)