mirror of
https://github.com/elicpeter/nyx.git
synced 2026-07-18 21:21:03 +02:00
Feat/configurable sanitizers and js precision (#32)
* chore: Exclude CLAUDE.md from Cargo.toml * feat: Add configurable analysis rules and CLI commands for custom sanitizers and terminators * feat: Enhance resource management and analysis efficiency - Implemented parallel summary merging in `scan_filesystem` using rayon for improved performance. - Introduced `GlobalSummaries::merge()` for efficient merging of summaries. - Optimized file reading and hashing to eliminate redundant I/O operations. - Added `should_scan_with_hash()` and `upsert_file_with_hash()` methods to streamline file processing. - Enhanced taint analysis with in-place mutations to reduce memory allocations. - Updated resource acquisition patterns to exclude false positives for `freopen` and wrapper functions. * feat: Implement severity downgrade for findings in non-production paths and add source kind inference * feat: Update versioning information in SECURITY.md for new stable line * feat: Update categories in Cargo.toml to include parser-implementations and text-processing * feat: Update dependencies in Cargo.lock for improved compatibility and performance * feat: Update dependencies in Cargo.lock and Cargo.toml for improved compatibility
This commit is contained in:
parent
f96a89e7c1
commit
19b578c5c4
37 changed files with 3775 additions and 432 deletions
|
|
@ -5,10 +5,10 @@ use crate::patterns::Severity;
|
|||
use crate::utils::Config;
|
||||
use crate::utils::project::get_project_info;
|
||||
use crate::walk::spawn_file_walker;
|
||||
use blake3;
|
||||
use bytesize::ByteSize;
|
||||
use chrono::{DateTime, Local};
|
||||
use console::style;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use rayon::prelude::*;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
|
@ -25,7 +25,13 @@ pub fn handle(
|
|||
let (project_name, db_path) = get_project_info(&build_path, database_dir)?;
|
||||
|
||||
if force || !db_path.exists() {
|
||||
build_index(&project_name, &build_path, &db_path, config)?;
|
||||
build_index(
|
||||
&project_name,
|
||||
&build_path,
|
||||
&db_path,
|
||||
config,
|
||||
!config.output.quiet,
|
||||
)?;
|
||||
println!(
|
||||
"✔ {} {}",
|
||||
style("Index built:").green(),
|
||||
|
|
@ -84,6 +90,7 @@ pub fn build_index(
|
|||
project_path: &std::path::Path,
|
||||
db_path: &std::path::Path,
|
||||
config: &Config,
|
||||
show_progress: bool,
|
||||
) -> NyxResult<()> {
|
||||
tracing::debug!("Building index for: {}", project_name);
|
||||
fs::File::create(db_path)?;
|
||||
|
|
@ -97,10 +104,27 @@ pub fn build_index(
|
|||
tracing::debug!("Cleaned index for: {}", project_name);
|
||||
|
||||
let (rx, handle) = spawn_file_walker(project_path, config);
|
||||
// Drain the channel BEFORE joining — the bounded channel will deadlock
|
||||
// if we join first and the walker blocks on send.
|
||||
let paths: Vec<PathBuf> = rx.into_iter().flatten().collect();
|
||||
if let Err(err) = handle.join() {
|
||||
tracing::error!("walker thread panicked: {:#?}", err);
|
||||
}
|
||||
let paths: Vec<PathBuf> = rx.into_iter().flatten().collect();
|
||||
|
||||
let pb = if show_progress {
|
||||
let pb = ProgressBar::new(paths.len() as u64);
|
||||
pb.set_style(
|
||||
ProgressStyle::with_template(
|
||||
"{spinner:.green} {msg} [{bar:30.cyan/blue}] {pos}/{len} ({eta})",
|
||||
)
|
||||
.unwrap()
|
||||
.progress_chars("##-"),
|
||||
);
|
||||
pb.set_message("Indexing files");
|
||||
pb
|
||||
} else {
|
||||
ProgressBar::hidden()
|
||||
};
|
||||
|
||||
paths
|
||||
.into_par_iter()
|
||||
|
|
@ -108,18 +132,15 @@ pub fn build_index(
|
|||
let mut idx = Indexer::from_pool(project_name, &pool)?;
|
||||
|
||||
// Read once, hash once — pass bytes to both rule execution and
|
||||
// summary extraction.
|
||||
// summary extraction. Use pre-computed hash for upsert to avoid
|
||||
// a redundant file read inside upsert_file.
|
||||
let bytes = std::fs::read(&path)?;
|
||||
let hash = {
|
||||
let mut hasher = blake3::Hasher::new();
|
||||
hasher.update(&bytes);
|
||||
hasher.finalize().as_bytes().to_vec()
|
||||
};
|
||||
let hash = Indexer::digest_bytes(&bytes);
|
||||
|
||||
// Run AST-only rules (no taint yet — summaries come later in scan)
|
||||
let issues =
|
||||
crate::commands::scan::run_rules_on_bytes(&bytes, &path, config, None, None)?;
|
||||
let file_id = idx.upsert_file(&path)?;
|
||||
let file_id = idx.upsert_file_with_hash(&path, &hash)?;
|
||||
|
||||
let rows: Vec<IssueRow> = issues
|
||||
.iter()
|
||||
|
|
@ -144,8 +165,10 @@ pub fn build_index(
|
|||
idx.replace_summaries_for_file(&path, &hash, &sums)?;
|
||||
}
|
||||
|
||||
pb.inc(1);
|
||||
Ok(())
|
||||
})?;
|
||||
pb.finish_and_clear();
|
||||
|
||||
{
|
||||
let idx = Indexer::from_pool(project_name, &pool)?;
|
||||
|
|
@ -170,7 +193,7 @@ fn build_index_creates_db_and_registers_files() {
|
|||
|
||||
let db_path = td.path().join("proj.sqlite");
|
||||
|
||||
build_index("proj", &project_dir, &db_path, &cfg).expect("index build should succeed");
|
||||
build_index("proj", &project_dir, &db_path, &cfg, false).expect("index build should succeed");
|
||||
|
||||
// ── Assert ────────────────────────────────────────────────────────────────
|
||||
assert!(db_path.is_file(), "SQLite file must exist");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue