From 3721121494823889f1e0500c3ec9a4c562115451 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 14 Apr 2015 16:01:33 +0000 Subject: Improve version guessing. Change-Id: I3a462f170521c4296e82ea1d2567a7ca7ed476c9 --- morphlib/plugins/cve_check_plugin.py | 73 +++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/morphlib/plugins/cve_check_plugin.py b/morphlib/plugins/cve_check_plugin.py index 26bb987c..3179d797 100644 --- a/morphlib/plugins/cve_check_plugin.py +++ b/morphlib/plugins/cve_check_plugin.py @@ -19,6 +19,7 @@ import warnings +import re import cliapp import morphlib @@ -55,6 +56,7 @@ class CVECheckPlugin(cliapp.Plugin): self.lrc, self.rrc = morphlib.util.new_repo_caches(self.app) self.resolver = morphlib.artifactresolver.ArtifactResolver() self.cve_db = CVEDataBase() + self.version_guesser = VersionGuesser() for system_filename in system_filenames: self.certify_system(repo, ref, system_filename) @@ -100,7 +102,7 @@ class CVECheckPlugin(cliapp.Plugin): self.lrc.cache_repo(source.repo_name) cached = self.lrc.get_repo(source.repo_name) - version = cached.version_guess(ref) + version = self.version_guesser.guess_version(cached, ref) self.cve_db.check_vulnerability(name, version) @@ -180,3 +182,72 @@ class CVEDataBase: s.check_vulnerability(version) break + + +class ProjectVersionGuesser(object): + + def __init__(self, interesting_files): + self.interesting_files = interesting_files + + def file_contents(self, cached, ref, tree): + filenames = [x for x in self.interesting_files if x in tree] + if filenames: + for filename in filenames: + yield filename, cached.read_file(filename, ref) + +class AutotoolsVersionGuesser(ProjectVersionGuesser): + + def __init__(self): + ProjectVersionGuesser.__init__(self, [ + 'configure.ac', + 'configure.in', + 'configure.ac.in', + 'configure.in.in', + ]) + + def guess_version(self, cached, ref, tree): + version = None + for filename, data in self.file_contents(cached, ref, tree): + # First, try to grep for AC_INIT() + version = self._check_ac_init(data) + if version: + break + + return version + + def _check_ac_init(self, data): + data = data.replace('\n', ' ') + for macro in ['AC_INIT', 'AM_INIT_AUTOMAKE']: + pattern = r'.*%s\((.*?)\).*' % macro + if not re.match(pattern, data): + continue + acinit = re.sub(pattern, r'\1', data) + if acinit: + version = acinit.split(',') + if macro == 'AM_INIT_AUTOMAKE' and len(version) == 1: + continue + version = version[0] if len(version) == 1 else version[1] + version = re.sub('[\[\]]', '', version).strip() + version = version.split()[0] + if version: + if version and version[0].isdigit(): + return version + return None + +class VersionGuesser(object): + + def __init__(self): + self.guessers = [ + AutotoolsVersionGuesser() + ] + + def guess_version(self, cached, ref): + version = None + tree = cached.list_files(ref, recurse=False) + for guesser in self.guessers: + version = guesser.guess_version(cached, ref, tree) + if version: + return version + + # Fall back to `git describe` which always gives something + return cached.version_guess(ref) -- cgit v1.2.1