summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/cve-check.bbclass10
-rw-r--r--meta/lib/oe/cve_check.py58
-rw-r--r--meta/lib/oeqa/selftest/cases/cve_check.py27
3 files changed, 90 insertions, 5 deletions
diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass
index d843e7c4ac..646cc879dd 100644
--- a/meta/classes/cve-check.bbclass
+++ b/meta/classes/cve-check.bbclass
@@ -206,7 +206,7 @@ def check_cves(d, patched_cves):
206 """ 206 """
207 Connect to the NVD database and find unpatched cves. 207 Connect to the NVD database and find unpatched cves.
208 """ 208 """
209 from distutils.version import LooseVersion 209 from oe.cve_check import Version
210 210
211 pn = d.getVar("PN") 211 pn = d.getVar("PN")
212 real_pv = d.getVar("PV") 212 real_pv = d.getVar("PV")
@@ -263,8 +263,8 @@ def check_cves(d, patched_cves):
263 else: 263 else:
264 if operator_start: 264 if operator_start:
265 try: 265 try:
266 vulnerable_start = (operator_start == '>=' and LooseVersion(pv) >= LooseVersion(version_start)) 266 vulnerable_start = (operator_start == '>=' and Version(pv) >= Version(version_start))
267 vulnerable_start |= (operator_start == '>' and LooseVersion(pv) > LooseVersion(version_start)) 267 vulnerable_start |= (operator_start == '>' and Version(pv) > Version(version_start))
268 except: 268 except:
269 bb.warn("%s: Failed to compare %s %s %s for %s" % 269 bb.warn("%s: Failed to compare %s %s %s for %s" %
270 (product, pv, operator_start, version_start, cve)) 270 (product, pv, operator_start, version_start, cve))
@@ -274,8 +274,8 @@ def check_cves(d, patched_cves):
274 274
275 if operator_end: 275 if operator_end:
276 try: 276 try:
277 vulnerable_end = (operator_end == '<=' and LooseVersion(pv) <= LooseVersion(version_end)) 277 vulnerable_end = (operator_end == '<=' and Version(pv) <= Version(version_end) )
278 vulnerable_end |= (operator_end == '<' and LooseVersion(pv) < LooseVersion(version_end)) 278 vulnerable_end |= (operator_end == '<' and Version(pv) < Version(version_end) )
279 except: 279 except:
280 bb.warn("%s: Failed to compare %s %s %s for %s" % 280 bb.warn("%s: Failed to compare %s %s %s for %s" %
281 (product, pv, operator_end, version_end, cve)) 281 (product, pv, operator_end, version_end, cve))
diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py
new file mode 100644
index 0000000000..ec48a3f829
--- /dev/null
+++ b/meta/lib/oe/cve_check.py
@@ -0,0 +1,58 @@
1import collections
2import re
3import itertools
4
5_Version = collections.namedtuple(
6 "_Version", ["release", "pre_l", "pre_v"]
7)
8
9class Version():
10 _version_pattern = r"""v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?"""
11 _regex = re.compile(r"^\s*" + _version_pattern + r"\s*$", re.VERBOSE | re.IGNORECASE)
12 def __init__(self, version):
13 match = self._regex.search(version)
14 if not match:
15 raise Exception("Invalid version: '{0}'".format(version))
16
17 self._version = _Version(
18 release=tuple(int(i) for i in match.group("release").replace("-",".").split(".")),
19 pre_l=match.group("pre_l"),
20 pre_v=match.group("pre_v")
21 )
22
23 self._key = _cmpkey(
24 self._version.release,
25 self._version.pre_l,
26 self._version.pre_v
27 )
28
29 def __le__(self, other):
30 if not isinstance(other, Version):
31 return NotImplemented
32 return self._key <= other._key
33
34 def __lt__(self, other):
35 if not isinstance(other, Version):
36 return NotImplemented
37 return self._key < other._key
38
39 def __ge__(self, other):
40 if not isinstance(other, Version):
41 return NotImplemented
42 return self._key >= other._key
43
44 def __gt__(self, other):
45 if not isinstance(other, Version):
46 return NotImplemented
47 return self._key > other._key
48
49def _cmpkey(release, pre_l, pre_v):
50 # remove leading 0
51 _release = tuple(
52 reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
53 )
54 if pre_l is None and pre_v is None:
55 _pre = float('inf')
56 else:
57 _pre = float(pre_v) if pre_v else float('-inf')
58 return _release, _pre
diff --git a/meta/lib/oeqa/selftest/cases/cve_check.py b/meta/lib/oeqa/selftest/cases/cve_check.py
new file mode 100644
index 0000000000..35e2b29a9a
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/cve_check.py
@@ -0,0 +1,27 @@
1from oe.cve_check import Version
2from oeqa.selftest.case import OESelftestTestCase
3
4class CVECheck(OESelftestTestCase):
5
6 def test_version_compare(self):
7 result = Version("100") > Version("99")
8 self.assertTrue( result, msg="Failed to compare version '100' > '99'")
9 result = Version("2.3.1") > Version("2.2.3")
10 self.assertTrue( result, msg="Failed to compare version '2.3.1' > '2.2.3'")
11 result = Version("2021-01-21") > Version("2020-12-25")
12 self.assertTrue( result, msg="Failed to compare version '2021-01-21' > '2020-12-25'")
13 result = Version("1.2-20200910") < Version("1.2-20200920")
14 self.assertTrue( result, msg="Failed to compare version '1.2-20200910' < '1.2-20200920'")
15
16 result = Version("1.0") >= Version("1.0beta")
17 self.assertTrue( result, msg="Failed to compare version '1.0' >= '1.0beta'")
18 result = Version("1.0-rc2") > Version("1.0-rc1")
19 self.assertTrue( result, msg="Failed to compare version '1.0-rc2' > '1.0-rc1'")
20 result = Version("1.0.alpha1") < Version("1.0")
21 self.assertTrue( result, msg="Failed to compare version '1.0.alpha1' < '1.0'")
22 result = Version("1.0_dev") <= Version("1.0")
23 self.assertTrue( result, msg="Failed to compare version '1.0_dev' <= '1.0'")
24
25 # ignore "p1" and "p2", so these should be equal
26 result = Version("1.0p2") <= Version("1.0p1") and Version("1.0p2") >= Version("1.0p1")
27 self.assertTrue( result ,msg="Failed to compare version '1.0p2' to '1.0p1'")