1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
//! Vulnerabilities represent the intersection of the [`Advisory`] database
//! and a particular `Cargo.lock` file.
use crate::{
advisory::{self, affected::FunctionPath, Advisory},
package::Package,
};
use serde::{Deserialize, Serialize};
/// A vulnerable package and the associated advisory
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Vulnerability {
/// Security advisory for which the package is vulnerable
pub advisory: advisory::Metadata,
/// Versions impacted by this vulnerability
pub versions: advisory::Versions,
/// More specific information about what this advisory affects (if available)
pub affected: Option<advisory::Affected>,
/// Vulnerable package
pub package: Package,
}
impl Vulnerability {
/// Create `Vulnerability` about a given [`Advisory`] and [`Package`]
pub fn new(advisory: &Advisory, package: &Package) -> Self {
Self {
advisory: advisory.metadata.clone(),
versions: advisory.versions.clone(),
affected: advisory.affected.clone(),
package: package.clone(),
}
}
/// Get the set of functions affected by this vulnerability (if available)
pub fn affected_functions(&self) -> Option<Vec<FunctionPath>> {
self.affected.as_ref().and_then(|affected| {
if affected.functions.is_empty() {
None
} else {
let mut result = vec![];
for (path, versions) in &affected.functions {
if versions
.iter()
.any(|req| req.matches(&self.package.version.clone()))
{
result.push(path.clone());
}
}
Some(result)
}
})
}
}