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 vers range crash #1598

Merged
merged 5 commits into from
Oct 15, 2024
Merged
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
30 changes: 22 additions & 8 deletions vulnerabilities/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,30 @@ def from_dict(cls, affected_pkg: dict):
"""
package = PackageURL(**affected_pkg["package"])
affected_version_range = None
if (
affected_pkg["affected_version_range"]
and affected_pkg["affected_version_range"] != "None"
):
affected_version_range = VersionRange.from_string(
affected_pkg["affected_version_range"]
)
affected_range = affected_pkg["affected_version_range"]

# TODO: "None" is a likely bug
if affected_range and affected_range != "None":
try:
affected_version_range = VersionRange.from_string(affected_range)
except:
tb = traceback.format_exc()
logger.error(
f"Cannot create AffectedPackage with invalid or unknown range: {affected_pkg!r} with error: {tb!r}"
)
return

fixed_version = affected_pkg["fixed_version"]
if fixed_version and affected_version_range:
# TODO: revisit after https://github.com/nexB/univers/issues/10
fixed_version = affected_version_range.version_class(fixed_version)

if not fixed_version and not affected_version_range:
logger.error(
f"Cannot create AffectedPackage without fixed version or affected range: {affected_pkg!r}"
)
return

return cls(
package=package,
affected_version_range=affected_version_range,
Expand Down Expand Up @@ -295,7 +307,9 @@ def from_dict(cls, advisory_data):
"aliases": advisory_data["aliases"],
"summary": advisory_data["summary"],
"affected_packages": [
AffectedPackage.from_dict(pkg) for pkg in advisory_data["affected_packages"]
AffectedPackage.from_dict(pkg)
for pkg in advisory_data["affected_packages"]
if pkg is not None
],
"references": [Reference.from_dict(ref) for ref in advisory_data["references"]],
"date_published": datetime.datetime.fromisoformat(date_published)
Expand Down
2 changes: 2 additions & 0 deletions vulnerabilities/improvers/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ def get_exact_purls(affected_package: AffectedPackage) -> Tuple[List[PackageURL]
... )
>>> assert expected == got
"""
if not affected_package:
return [], []

try:
vr = affected_package.affected_version_range
Expand Down
4 changes: 3 additions & 1 deletion vulnerabilities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,9 @@ def to_advisory_data(self) -> "AdvisoryData":
return AdvisoryData(
aliases=self.aliases,
summary=self.summary,
affected_packages=[AffectedPackage.from_dict(pkg) for pkg in self.affected_packages],
affected_packages=[
AffectedPackage.from_dict(pkg) for pkg in self.affected_packages if pkg
],
references=[Reference.from_dict(ref) for ref in self.references],
date_published=self.date_published,
weaknesses=self.weaknesses,
Expand Down
27 changes: 27 additions & 0 deletions vulnerabilities/tests/test_default_improver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from vulnerabilities.importer import Reference
from vulnerabilities.improver import Inference
from vulnerabilities.improvers.default import DefaultImprover
from vulnerabilities.improvers.default import get_exact_purls
from vulnerabilities.tests import util_tests

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
Expand Down Expand Up @@ -136,3 +137,29 @@ def test_default_improver_with_nvd():
for data in list(default_improver.get_inferences(AdvisoryData.from_dict(advisory_data)))
]
util_tests.check_results_against_json(result, expected_file)


def test_AffectedPackage_from_dict_should_not_crash_with_invalid_version_range():
package = PackageURL(
type="rpm",
namespace="rpms",
name="python",
qualifiers={},
subpath=None,
)

test_ranges = [
# foo is a non-existing range
"vers:foo/1.2.3",
# apache was not supported and returned from vulnerabilities.importers.apache_httpd.ApacheHTTPDImporter
"vers:apache/",
None,
]
for tr in test_ranges:
pkg = {
"package": package.to_dict(),
"affected_version_range": tr,
"fixed_version": None,
}

assert AffectedPackage.from_dict(pkg) is None
Loading