diff --git a/cve_bin_tool/parsers/rust.py b/cve_bin_tool/parsers/rust.py index 91133bea60..db292705fb 100644 --- a/cve_bin_tool/parsers/rust.py +++ b/cve_bin_tool/parsers/rust.py @@ -1,17 +1,61 @@ # Copyright (C) 2022 Intel Corporation # SPDX-License-Identifier: GPL-3.0-or-later +import re + from cve_bin_tool.parsers import Parser class RustParser(Parser): + """ + Parser implementation for Rust dependency files (Cargo.toml). + + This parser is designed to parse Rust dependency files (Cargo.toml) and generate + Package URL (PURL) strings based on the packages and their versions listed in the file. + + Attributes: + cve_db (CVEDB): The CVE database instance used for vulnerability information. + logger (Logger): The logger instance for logging messages and debugging information. + + Methods: + generate_purl(product, version, vendor): + Generates PURL after normalizing all components. + run_checker(filename): + Parse the Rust dependency file and yield valid PURLs for the packages listed in the file. + """ + def __init__(self, cve_db, logger): super().__init__(cve_db, logger) + self.purl_pkg_type = "cargo" + + def generate_purl(self, product, version, vendor, qualifier={}, subpath=None): + """Generates PURL after normalizing all components.""" + + product = re.sub(r"^[^a-zA-Z_]|[^a-zA-Z0-9_-]", "", product) + vendor = re.sub(r"^[^a-zA-Z_]|[^a-zA-Z0-9_-]", "", vendor) + version = re.sub(r"^[^0-9]|[^a-zA-Z0-9.+-]", "", version) + + if not re.match(r"^[a-zA-Z_]|[a-zA-Z0-9_-]", product): + return + if vendor == "": + vendor = "UNKNOWN" + if version == "": + version = "UNKNOWN" + + purl = super().generate_purl( + product, + version, + vendor, + qualifier, + subpath, + ) + + return purl def run_checker(self, filename): + """Parse the file and yield valid PURLs.""" self.filename = filename with open(filename) as fh: - # parse the multiline name and version format lines = fh.readlines() product = "" version = "" @@ -23,9 +67,9 @@ def run_checker(self, filename): else: if product == "" and version == "": continue - vendor = self.find_vendor(product, version) + vendors = self.find_vendor(product, version) + if vendors is not None: + yield from vendors product = "" version = "" - if vendor is not None: - yield from vendor self.logger.debug(f"Done scanning file: {self.filename}")