3636from typing import Tuple
3737
3838from binaryornot .helpers import is_binary_string
39+ from dateutil import parser as dateparser
3940from git import DiffIndex
4041from git import Repo
4142from license_expression import Licensing
4243from packageurl import PackageURL
44+ from univers .version_range import RANGE_CLASS_BY_SCHEMES
4345from univers .version_range import VersionRange
4446from univers .versions import Version
4547
4648from vulnerabilities .helpers import classproperty
4749from vulnerabilities .helpers import evolve_purl
48- from vulnerabilities .helpers import nearest_patched_package
4950from vulnerabilities .oval_parser import OvalParser
5051from vulnerabilities .severity_systems import SCORING_SYSTEMS
5152from vulnerabilities .severity_systems import ScoringSystem
@@ -510,13 +511,13 @@ class OvalImporter(Importer):
510511 """
511512
512513 @staticmethod
513- def create_purl (pkg_name : str , pkg_version : str , pkg_data : Mapping ) -> PackageURL :
514+ def create_purl (pkg_name : str , pkg_data : Mapping ) -> PackageURL :
514515 """
515516 Helper method for creating different purls for subclasses without them reimplementing
516517 get_data_from_xml_doc method
517518 Note: pkg_data must include 'type' of package
518519 """
519- return PackageURL (name = pkg_name , version = pkg_version , ** pkg_data )
520+ return PackageURL (name = pkg_name , ** pkg_data )
520521
521522 @staticmethod
522523 def _collect_pkgs (parsed_oval_data : Mapping ) -> Set :
@@ -550,28 +551,15 @@ def advisory_data(self) -> List[AdvisoryData]:
550551 for metadata , oval_file in self ._fetch ():
551552 try :
552553 oval_data = self .get_data_from_xml_doc (oval_file , metadata )
553- yield oval_data
554+ yield from oval_data
554555 except Exception :
555556 logger .error (
556557 f"Failed to get updated_advisories: { oval_file !r} "
557558 f"with { metadata !r} :\n " + traceback .format_exc ()
558559 )
559560 continue
560561
561- def set_api (self , all_pkgs : Iterable [str ]):
562- """
563- This method loads the self.pkg_manager_api with the specified packages.
564- It fetches and caches all the versions of these packages and exposes
565- them through self.pkg_manager_api.get(<package_name>). Example
566-
567- >> self.set_api(['electron'])
568- Assume 'electron' has only versions 1.0.0 and 1.2.0
569- >> assert self.pkg_manager_api.get('electron') == {'1.0.0','1.2.0'}
570-
571- """
572- raise NotImplementedError
573-
574- def get_data_from_xml_doc (self , xml_doc : ET .ElementTree , pkg_metadata = {}) -> List [AdvisoryData ]:
562+ def get_data_from_xml_doc (self , xml_doc : ET .ElementTree , pkg_metadata = {}) -> Iterable [AdvisoryData ]:
575563 """
576564 The orchestration method of the OvalDataSource. This method breaks an
577565 OVAL xml ElementTree into a list of `Advisory`.
@@ -584,10 +572,11 @@ def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> Lis
584572 """
585573
586574 all_adv = []
587- oval_doc = OvalParser (self .translations , xml_doc )
588- raw_data = oval_doc .get_data ()
589- all_pkgs = self ._collect_pkgs (raw_data )
590- self .set_api (all_pkgs )
575+ oval_parsed_data = OvalParser (self .translations , xml_doc )
576+ raw_data = oval_parsed_data .get_data ()
577+ oval_doc = oval_parsed_data .oval_document
578+ timestamp = oval_doc .getGenerator ().getTimestamp ()
579+ # all_pkgs = self._collect_pkgs(raw_data)
591580
592581 # convert definition_data to Advisory objects
593582 for definition_data in raw_data :
@@ -599,49 +588,28 @@ def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> Lis
599588 affected_packages = []
600589 for test_data in definition_data ["test_data" ]:
601590 for package_name in test_data ["package_list" ]:
602- if package_name and len (package_name ) >= 50 :
603- continue
604-
605- affected_version_range = test_data ["version_ranges" ] or set ()
606- version_class = version_class_by_package_type [pkg_metadata ["type" ]]
607- version_scheme = version_class .scheme
608-
609- affected_version_range = VersionRange .from_scheme_version_spec_string (
610- version_scheme , affected_version_range
611- )
612- all_versions = self .pkg_manager_api .get (package_name ).valid_versions
613-
614- # FIXME: what is this 50 DB limit? that's too small for versions
615- # FIXME: we should not drop data this way
616- # This filter is for filtering out long versions.
617- # 50 is limit because that's what db permits atm.
618- all_versions = [version for version in all_versions if len (version ) < 50 ]
619- if not all_versions :
620- continue
621-
622- affected_purls = []
623- safe_purls = []
624- for version in all_versions :
625- purl = self .create_purl (
626- pkg_name = package_name ,
627- pkg_version = version ,
628- pkg_data = pkg_metadata ,
591+ affected_version_range = test_data ["version_ranges" ]
592+ vrc = RANGE_CLASS_BY_SCHEMES [pkg_metadata ["type" ]]
593+ if affected_version_range :
594+ try :
595+ affected_version_range = vrc .from_native (affected_version_range )
596+ except Exception as e :
597+ logger .error (
598+ f"Failed to parse version range { affected_version_range !r} "
599+ f"for package { package_name !r} :\n { e } "
600+ )
601+ continue
602+ if package_name :
603+ affected_packages .append (
604+ AffectedPackage (
605+ package = self .create_purl (package_name , pkg_metadata ),
606+ affected_version_range = affected_version_range ,
607+ )
629608 )
630- if version_class (version ) in affected_version_range :
631- affected_purls .append (purl )
632- else :
633- safe_purls .append (purl )
634-
635- affected_packages .extend (
636- nearest_patched_package (affected_purls , safe_purls ),
637- )
638-
639- all_adv .append (
640- AdvisoryData (
641- summary = description ,
642- affected_packages = affected_packages ,
643- vulnerability_id = vuln_id ,
644- references = references ,
645- )
609+ yield AdvisoryData (
610+ aliases = [vuln_id ],
611+ summary = description ,
612+ affected_packages = affected_packages ,
613+ references = references ,
614+ date_published = dateparser .parse (timestamp ),
646615 )
647- return all_adv
0 commit comments