mirror of
https://github.com/imjasonh/rustvulncheck
synced 2026-07-08 04:08:07 +00:00
Make vuln_db.json output deterministic to minimize diff noise
- Sort entries by advisory_id before writing - Sort vulnerable_symbols within each entry by file/function/change_type - Sort diff_symbols output in ast_differ (HashSet iteration was random) - Add Ord/PartialOrd to ChangeType enum for sorting - Only update generated_at timestamp when entries actually changed - Add trailing newline to JSON output https://claude.ai/code/session_01P1LKP6aqGt68rQAXrF6kSE
This commit is contained in:
parent
aa46e782e5
commit
ce13ee0862
4 changed files with 33 additions and 6 deletions
|
|
@ -93,6 +93,14 @@ pub fn diff_symbols(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort for deterministic output: by file, then function, then change_type
|
||||||
|
results.sort_by(|a, b| {
|
||||||
|
a.file
|
||||||
|
.cmp(&b.file)
|
||||||
|
.then(a.function.cmp(&b.function))
|
||||||
|
.then(a.change_type.cmp(&b.change_type))
|
||||||
|
});
|
||||||
|
|
||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
21
src/db.rs
21
src/db.rs
|
|
@ -11,7 +11,7 @@ pub struct VulnDb {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single vulnerability entry with function-level detail.
|
/// A single vulnerability entry with function-level detail.
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VulnEntry {
|
pub struct VulnEntry {
|
||||||
pub advisory_id: String,
|
pub advisory_id: String,
|
||||||
pub package: String,
|
pub package: String,
|
||||||
|
|
@ -42,7 +42,24 @@ impl VulnDb {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_json(&self, path: &Path) -> anyhow::Result<()> {
|
pub fn write_json(&self, path: &Path) -> anyhow::Result<()> {
|
||||||
let json = serde_json::to_string_pretty(self)?;
|
// Sort for deterministic output to minimize diff noise
|
||||||
|
let mut sorted = self.entries.clone();
|
||||||
|
sorted.sort_by(|a, b| a.advisory_id.cmp(&b.advisory_id));
|
||||||
|
for entry in &mut sorted {
|
||||||
|
entry.vulnerable_symbols.sort_by(|a, b| {
|
||||||
|
a.file
|
||||||
|
.cmp(&b.file)
|
||||||
|
.then(a.function.cmp(&b.function))
|
||||||
|
.then(a.change_type.cmp(&b.change_type))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let sorted_db = VulnDb {
|
||||||
|
generated_at: self.generated_at.clone(),
|
||||||
|
entries: sorted,
|
||||||
|
};
|
||||||
|
let mut json = serde_json::to_string_pretty(&sorted_db)?;
|
||||||
|
json.push('\n');
|
||||||
std::fs::write(path, json)?;
|
std::fs::write(path, json)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ pub struct VulnerableSymbol {
|
||||||
pub change_type: ChangeType,
|
pub change_type: ChangeType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum ChangeType {
|
pub enum ChangeType {
|
||||||
Modified,
|
|
||||||
Added,
|
Added,
|
||||||
Deleted,
|
Deleted,
|
||||||
|
Modified,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract function signatures by fetching full file contents and AST-diffing.
|
/// Extract function signatures by fetching full file contents and AST-diffing.
|
||||||
|
|
|
||||||
|
|
@ -395,8 +395,10 @@ fn run_enrich(args: EnrichArgs) -> Result<()> {
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update timestamp
|
// Only update timestamp if we actually changed something
|
||||||
vuln_db.update_timestamp();
|
if new_count > 0 || re_enriched_count > 0 {
|
||||||
|
vuln_db.update_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
// Step 6: Write output
|
// Step 6: Write output
|
||||||
let entries_with_symbols = vuln_db
|
let entries_with_symbols = vuln_db
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue