Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: upgrade from LegacyVersion #2679

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions cve_bin_tool/cve_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from typing import DefaultDict, Dict, List, Tuple

from packaging.version import Version
from packaging.version import parse as parse_version
from packaging.version import parse as packaging_parse
from rich.console import Console

from cve_bin_tool.cvedb import DBNAME, DISK_LOCATION_DEFAULT
Expand Down Expand Up @@ -97,7 +97,7 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):

# Need to manipulate version to ensure canonical form of version

parsed_version, parsed_version_between = self.canonical_convert(product_info)
parsed_version = self.canonical_convert(product_info)
# If canonical form of version numbering not found, exit
if parsed_version == "UNKNOWN":
return
Expand Down Expand Up @@ -139,19 +139,18 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
version_start_excluding = self.letter_convert(version_start_excluding)
version_end_including = self.letter_convert(version_end_including)
version_end_excluding = self.letter_convert(version_end_excluding)
parsed_version = parsed_version_between

# check the start range
passes_start = False
if (
version_start_including is not self.RANGE_UNSET
and parsed_version >= parse_version(version_start_including)
and parsed_version >= self.parse_version(version_start_including)
):
passes_start = True

if (
version_start_excluding is not self.RANGE_UNSET
and parsed_version > parse_version(version_start_excluding)
and parsed_version > self.parse_version(version_start_excluding)
):
passes_start = True

Expand All @@ -166,13 +165,13 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
passes_end = False
if (
version_end_including is not self.RANGE_UNSET
and parsed_version <= parse_version(version_end_including)
and parsed_version <= self.parse_version(version_end_including)
):
passes_end = True

if (
version_end_excluding is not self.RANGE_UNSET
and parsed_version < parse_version(version_end_excluding)
and parsed_version < self.parse_version(version_end_excluding)
):
passes_end = True

Expand Down Expand Up @@ -307,17 +306,15 @@ def letter_convert(self, version: str) -> str:
version = f"{version[:-1]}.{self.ALPHA_TO_NUM[last_char]}"
return version

VersionType = Version

def canonical_convert(
self, product_info: ProductInfo
) -> Tuple[VersionType, VersionType]:
version_between = parse_version("")
def canonical_convert(self, product_info: ProductInfo) -> Tuple[Version]:
if product_info.version == "":
return parse_version(product_info.version), version_between
return self.parse_version(product_info.version)

# if we're using openssl or libjpeg, we need to convert letters to numbers
if product_info.product in {"openssl", "libjpeg"}:
pv = re.search(r"\d[.\d]*[a-z]?", product_info.version)
version_between = parse_version(self.letter_convert(pv.group(0)))
parsed_version = self.parse_version(self.letter_convert(pv.group(0)))

else:
# Ensure canonical form of version numbering
if ":" in product_info.version:
Expand All @@ -333,8 +330,26 @@ def canonical_convert(
f"error parsing {product_info.vendor}.{product_info.product} v{product_info.version} - manual inspection required"
)
else:
parsed_version = parse_version(pv.group(0))
return parsed_version, version_between
parsed_version = self.parse_version(pv.group(0))
return parsed_version

def parse_version(self, version_string: str) -> Tuple[Version]:
# convert _ to . for versions 1_2_3 -> 1.2.3
version_string = re.sub("_", ".", version_string)

# handle leading product name like curl-7.57.0 by truncating
version_string = re.sub("[a-zA-Z]*-", "", version_string)

# Or just convert the - to a . for cases like `5-1.6`
version_string = re.sub("-", ".", version_string)

# handle trailing letters a la '1.6.3.kdc' by truncating
version_string = re.sub(r"\.[a-zA-Z]*", "", version_string)

# Otherwise just try to parse it with packaging's parse
parsed_version = packaging_parse(version_string)

return parsed_version

def affected(self):
"""Returns list of vendor.product and version tuples identified from
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jinja2>=2.11.3
jsonschema>=3.0.2
lib4sbom>=0.3.0
python-gnupg
packaging<22.0
packaging
plotly
pyyaml>=5.4
requests
Expand Down