From 40abc660d497901f75a7ad4a901b93e8dad0eeef Mon Sep 17 00:00:00 2001 From: Thomas Perale Date: Fri, 18 Sep 2026 11:11:42 +0200 Subject: [PATCH] utils/checkpackagelib: check IGNORE_CVES identifiers match patch trailers The ability to check with `make check-package` the 'IGNORE_CVES' variable content reference an existing patches was added in commit [1]. This commit extend it to actually check that the entries that are referenced in the 'IGNORE_CVES' variable are matching the trailers in the referenced patch. With this change the following `foo.mk` content: ``` FOO_IGNORE_CVES += CVE-2000-1234 ``` Running `make check-package` will output an error if the content of the patch is the following: ``` CVE: CVE-2001-1234 ``` [1] b00ac4e346 utils/checkpackagelib: add new check MissingCVEPatch Signed-off-by: Thomas Perale [Arnout: adapt to the trailers to using regex] Signed-off-by: Arnout Vandecappelle --- utils/checkpackagelib/lib_mk.py | 31 ++++++++++++++++++++++----- utils/checkpackagelib/test_lib_mk.py | 32 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/utils/checkpackagelib/lib_mk.py b/utils/checkpackagelib/lib_mk.py index 1fa056cbf4..297cb14460 100644 --- a/utils/checkpackagelib/lib_mk.py +++ b/utils/checkpackagelib/lib_mk.py @@ -120,12 +120,14 @@ class Indent(_CheckFunction): class MissingCVEPatch(_CheckFunction): PATCH_COMMENT = re.compile(r"^#\s*(\S+\.patch)\s*$") - IGNORE_CVES = re.compile(r"^[A-Z0-9_]+_IGNORE_CVES\s*\+?=") - CVE_TAG_IN_PATCH = re.compile(r"^CVE: *([\w-]+)$") + IGNORE_CVES = re.compile(r"^[A-Z0-9_]+_IGNORE_CVES\s*\+?=\s*(.*)$") + CVE_TAG_IN_PATCH = re.compile(r"^CVE: *([\w-]+)$", re.M) def before(self): self.pending_patches = [] + self.pending_cves = [] self.package_dir = Path(self.filename).parent + self.line_continuation = False def check_patch_files(self): for patch_lineno, patch_name, patch_text in self.pending_patches: @@ -136,11 +138,18 @@ class MissingCVEPatch(_CheckFunction): .format(self.filename, patch_lineno, patch_name), patch_text] - if not any(map(self.CVE_TAG_IN_PATCH.match, patch_file.open())): + matches = self.CVE_TAG_IN_PATCH.finditer(patch_file.read_text()) + trailers = [match.group(1) for match in matches] + if not trailers: return ["{}: patch file '{}' is missing 'CVE:' tag" .format(self.filename, patch_name), patch_text] + if set(self.pending_cves) != set(trailers): + return ["{}: patch file '{}' 'CVE:' tag(s) '{}' does not match the ignored identifier(s) '{}'" + .format(self.filename, patch_name, ", ".join(trailers), ", ".join(self.pending_cves)), + patch_text] + def check_line(self, lineno, text): m = self.PATCH_COMMENT.match(text.rstrip()) if m: @@ -152,9 +161,21 @@ class MissingCVEPatch(_CheckFunction): if text.lstrip().startswith("#"): return - if self.IGNORE_CVES.search(text): - return self.check_patch_files() + m = self.IGNORE_CVES.search(text) + if m or self.line_continuation: + value = (m.group(1) if m else text).rstrip() + self.line_continuation = value.endswith("\\") + if self.line_continuation: + value = value[:-1] + self.pending_cves += value.split() + if self.line_continuation: + return + result = self.check_patch_files() + self.pending_cves = [] + self.pending_patches = [] + return result + self.pending_cves = [] self.pending_patches = [] diff --git a/utils/checkpackagelib/test_lib_mk.py b/utils/checkpackagelib/test_lib_mk.py index 9d2950ef79..1bbb0af20c 100644 --- a/utils/checkpackagelib/test_lib_mk.py +++ b/utils/checkpackagelib/test_lib_mk.py @@ -250,6 +250,38 @@ MissingCVEPatch = [ '# 0001-some-fix.patch\n' 'FOO_IGNORE_CVES += GHSA-abcd-1234-efgh\n', []), + ('CVE tag does not match ignored identifier', + {'0001-some-fix.patch': 'CVE: CVE-2000-1234'}, + '# 0001-some-fix.patch\n' + 'FOO_IGNORE_CVES += CVE-2001-1234\n', + [['{}: patch file \'0001-some-fix.patch\' \'CVE:\' tag(s) \'CVE-2000-1234\' ' + 'does not match the ignored identifier(s) \'CVE-2001-1234\'', + '# 0001-some-fix.patch\n']]), + ('multiple ignored identifiers, patch matches one', + {'0001-some-fix.patch': 'CVE: CVE-2000-1234'}, + '# 0001-some-fix.patch\n' + 'FOO_IGNORE_CVES += CVE-2000-1234 CVE-2001-1234\n', + [['{}: patch file \'0001-some-fix.patch\' \'CVE:\' tag(s) \'CVE-2000-1234\' ' + 'does not match the ignored identifier(s) \'CVE-2000-1234, CVE-2001-1234\'', + '# 0001-some-fix.patch\n']]), + ('multiple ignored identifiers, all referenced across patch', + {'0001-some-fix.patch': 'CVE: CVE-2000-1234\nCVE: CVE-2001-1234\n'}, + '# 0001-some-fix.patch\n' + 'FOO_IGNORE_CVES += CVE-2000-1234 CVE-2001-1234\n', + []), + ('multiple ignored identifiers, all referenced across multiple patches', + {'0001-some-fix.patch': 'CVE: CVE-2000-1234\nCVE: CVE-2001-1234', + '0002-other-fix.patch': 'CVE: CVE-2000-1234\nCVE: CVE-2001-1234'}, + '# 0001-some-fix.patch\n' + '# 0002-other-fix.patch\n' + 'FOO_IGNORE_CVES += CVE-2000-1234 CVE-2001-1234\n', + []), + ('ignored identifiers split across continuation lines', + {'0001-some-fix.patch': 'CVE: CVE-2000-1234\nCVE: CVE-2001-1234\n'}, + '# 0001-some-fix.patch\n' + 'FOO_IGNORE_CVES += CVE-2000-1234 \\\n' + '\tCVE-2001-1234\n', + []), ]