@@ -121,43 +121,43 @@ def cves_from_reference(reference):
121121 return cves
122122
123123
124+ def _yield_packages (pkg_name , pkg_ns , constraints , invert ):
125+ """
126+ Generate AffectedPackageV2 objects for a list of constraints.
127+ """
128+ for comparator , version , slot_value in constraints :
129+ qualifiers = {"slot" : slot_value } if slot_value else {}
130+ purl = PackageURL (type = "ebuild" , name = pkg_name , namespace = pkg_ns , qualifiers = qualifiers )
131+
132+ try :
133+ constraint = VersionConstraint (version = GentooVersion (version ), comparator = comparator )
134+
135+ if invert :
136+ constraint = constraint .invert ()
137+
138+ yield AffectedPackageV2 (
139+ package = purl ,
140+ affected_version_range = EbuildVersionRange (constraints = [constraint ]),
141+ fixed_version_range = None ,
142+ )
143+ except InvalidVersion as e :
144+ logger .error (f"InvalidVersion constraints version: { version } error:{ e } " )
145+
146+
124147def affected_and_safe_purls (affected_elem ):
125- constraints = []
126148 for pkg in affected_elem :
127149 name = pkg .attrib .get ("name" )
128150 if not name :
129151 continue
130152 pkg_ns , _ , pkg_name = name .rpartition ("/" )
131- purl = PackageURL (type = "ebuild" , name = pkg_name , namespace = pkg_ns )
132- safe_versions , affected_versions = get_safe_and_affected_versions (pkg )
133-
134- for version in safe_versions :
135- try :
136- constraints .append (
137- VersionConstraint (version = GentooVersion (version ), comparator = "=" ).invert ()
138- )
139- except InvalidVersion as e :
140- logger .error (f"InvalidVersion - version: { version } - error:{ e } " )
141-
142- for version in affected_versions :
143- try :
144- constraints .append (
145- VersionConstraint (version = GentooVersion (version ), comparator = "=" )
146- )
147- except InvalidVersion as e :
148- logger .error (f"InvalidVersion - version: { version } - error:{ e } " )
149-
150- if not constraints :
151- continue
152153
153- yield AffectedPackageV2 (
154- package = purl ,
155- affected_version_range = EbuildVersionRange (constraints = constraints ),
156- fixed_version_range = None ,
157- )
154+ safe_constraints , affected_constraints = get_safe_and_affected_constraints (pkg )
155+
156+ yield from _yield_packages (pkg_name , pkg_ns , affected_constraints , invert = False )
157+ yield from _yield_packages (pkg_name , pkg_ns , safe_constraints , invert = True )
158158
159159
160- def get_safe_and_affected_versions (pkg ):
160+ def get_safe_and_affected_constraints (pkg ):
161161 # TODO : Revisit why we are skipping some versions in gentoo importer
162162 skip_versions = {"1.3*" , "7.3*" , "7.4*" }
163163 safe_versions = set ()
@@ -166,27 +166,20 @@ def get_safe_and_affected_versions(pkg):
166166 if info .text in skip_versions :
167167 continue
168168
169- if info .attrib .get ("range" ):
170- if len (info .attrib .get ("range" )) > 2 :
171- continue
169+ # All possible values of info.attrib['range'] =
170+ # {'gt', 'lt', 'rle', 'rge', 'rgt', 'le', 'ge', 'eq'}, out of
171+ # which ('rle', 'rge', 'rgt') are ignored, because they compare
172+ # 'release' not the 'version'.
173+ range_value = info .attrib .get ("range" )
174+ slot_value = info .attrib .get ("slot" )
175+ comparator_dict = {"gt" : ">" , "lt" : "<" , "ge" : ">=" , "le" : "<=" , "eq" : "=" }
176+ comparator = comparator_dict .get (range_value )
177+ if not comparator :
178+ continue
172179
173180 if info .tag == "unaffected" :
174- # quick hack, to know whether this
175- # version lies in this range, 'e' stands for
176- # equal, which is paired with 'greater' or 'less'.
177- # All possible values of info.attrib['range'] =
178- # {'gt', 'lt', 'rle', 'rge', 'rgt', 'le', 'ge', 'eq'}, out of
179- # which ('rle', 'rge', 'rgt') are ignored, because they compare
180- # 'release' not the 'version'.
181- if "e" in info .attrib ["range" ]:
182- safe_versions .add (info .text )
183- else :
184- affected_versions .add (info .text )
181+ safe_versions .add ((comparator , info .text , slot_value ))
185182
186183 elif info .tag == "vulnerable" :
187- if "e" in info .attrib ["range" ]:
188- affected_versions .add (info .text )
189- else :
190- safe_versions .add (info .text )
191-
184+ affected_versions .add ((comparator , info .text , slot_value ))
192185 return safe_versions , affected_versions
0 commit comments