1
0
Fork 0
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:
Claude 2026-03-25 16:06:24 +00:00
parent aa46e782e5
commit ce13ee0862
No known key found for this signature in database
4 changed files with 33 additions and 6 deletions

View file

@ -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
} }

View file

@ -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(())
} }

View file

@ -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.

View file

@ -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