bench: harden architecture scan evidence #1
1 changed files with 75 additions and 1 deletions
fix(fold): normalize imported finding paths
commit
e03c2a299b
76
src/fold.rs
76
src/fold.rs
|
|
@ -207,19 +207,45 @@ fn native_backend(value: &Value) -> String {
|
|||
}
|
||||
|
||||
fn find_file(building: &Building, path: &str) -> Option<String> {
|
||||
let normalized = path.replace('\\', "/");
|
||||
let normalized = normalize_lexical_path(path);
|
||||
building
|
||||
.nodes
|
||||
.iter()
|
||||
.filter(|node| node.kind == NodeKind::File)
|
||||
.find(|node| {
|
||||
node.path.as_deref().is_some_and(|candidate| {
|
||||
let candidate = normalize_lexical_path(candidate);
|
||||
normalized == candidate || normalized.ends_with(&format!("/{candidate}"))
|
||||
})
|
||||
})
|
||||
.map(|node| node.id.clone())
|
||||
}
|
||||
|
||||
fn normalize_lexical_path(path: &str) -> String {
|
||||
let portable = path.replace('\\', "/");
|
||||
let absolute = portable.starts_with('/');
|
||||
let mut components = Vec::new();
|
||||
for component in portable.split('/') {
|
||||
match component {
|
||||
"" | "." => {}
|
||||
".." => {
|
||||
if components.last().is_some_and(|previous| *previous != "..") {
|
||||
components.pop();
|
||||
} else if !absolute {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
_ => components.push(component),
|
||||
}
|
||||
}
|
||||
let normalized = components.join("/");
|
||||
if absolute {
|
||||
format!("/{normalized}")
|
||||
} else {
|
||||
normalized
|
||||
}
|
||||
}
|
||||
|
||||
fn confidence_value(confidence: &str) -> f64 {
|
||||
match confidence {
|
||||
"concrete-witness" => 1.0,
|
||||
|
|
@ -258,4 +284,52 @@ mod tests {
|
|||
assert_eq!(finding.attributes["confidence"], "proved");
|
||||
assert_eq!(finding.attributes["backend"], "source");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalizes_fold_paths_without_matching_a_missing_neighbor() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let header = dir.path().join("include/yams/core/types.h");
|
||||
fs::create_dir_all(header.parent().unwrap()).unwrap();
|
||||
fs::write(&header, "struct Type {};\n").unwrap();
|
||||
let report = dir.path().join("fold.sarif");
|
||||
fs::write(
|
||||
&report,
|
||||
r#"{
|
||||
"runs": [{
|
||||
"results": [
|
||||
{
|
||||
"ruleId": "fold.valid",
|
||||
"message": {"text": "valid"},
|
||||
"locations": [{"physicalLocation": {
|
||||
"artifactLocation": {"uri": "../../include/yams/daemon/components/../../core/types.h"},
|
||||
"region": {"startLine": 1}
|
||||
}}]
|
||||
},
|
||||
{
|
||||
"ruleId": "fold.missing",
|
||||
"message": {"text": "missing"},
|
||||
"locations": [{"physicalLocation": {
|
||||
"artifactLocation": {"uri": "../../include/yams/daemon/components/../../core/missing.h"},
|
||||
"region": {"startLine": 1}
|
||||
}}]
|
||||
}
|
||||
]
|
||||
}]
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut building = scan(dir.path()).unwrap();
|
||||
assert_eq!(import_findings(&mut building, &report).unwrap(), 1);
|
||||
assert_eq!(
|
||||
building
|
||||
.nodes
|
||||
.iter()
|
||||
.filter(|node| node.kind == NodeKind::Finding)
|
||||
.count(),
|
||||
1
|
||||
);
|
||||
assert_eq!(building.diagnostics.len(), 1);
|
||||
assert!(building.diagnostics[0].message.contains("missing.h"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue