style(comments): remove decorative comment borders across files for consistency and cleaner code structure

This commit is contained in:
elipeter 2026-06-02 14:03:07 -05:00
parent 321d0a61ab
commit 879f965379
39 changed files with 16 additions and 379 deletions

View file

@ -1043,9 +1043,7 @@ fn downgrade_severity(s: Severity) -> Severity {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// ParsedSource + ParsedFile: shared parse/CFG pipeline // ParsedSource + ParsedFile: shared parse/CFG pipeline
// ─────────────────────────────────────────────────────────────────────────────
/// Level 1: parsed tree + lang info. No CFG construction. /// Level 1: parsed tree + lang info. No CFG construction.
struct ParsedSource<'a> { struct ParsedSource<'a> {
@ -2161,9 +2159,7 @@ impl<'a> ParsedFile<'a> {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Pass 1: Extract function summaries (no taint analysis) // Pass 1: Extract function summaries (no taint analysis)
// ─────────────────────────────────────────────────────────────────────────────
/// Extract function summaries from pre-read bytes. /// Extract function summaries from pre-read bytes.
/// ///
@ -2453,9 +2449,7 @@ pub fn extract_all_summaries_from_bytes(
)) ))
} }
// ─────────────────────────────────────────────────────────────────────────────
// Constant-argument suppression helper // Constant-argument suppression helper
// ─────────────────────────────────────────────────────────────────────────────
/// Returns `true` when the captured call node has only literal arguments /// Returns `true` when the captured call node has only literal arguments
/// (string, number, boolean, null/nil/none), or identifier arguments that /// (string, number, boolean, null/nil/none), or identifier arguments that
@ -5355,9 +5349,7 @@ fn has_interpolation(node: tree_sitter::Node) -> bool {
false false
} }
// ─────────────────────────────────────────────────────────────────────────────
// Layer B: AST pattern suppression when taint confirms safety // Layer B: AST pattern suppression when taint confirms safety
// ─────────────────────────────────────────────────────────────────────────────
/// Map the second segment of a pattern ID (e.g. "cmdi" from "py.cmdi.os_system") /// Map the second segment of a pattern ID (e.g. "cmdi" from "py.cmdi.os_system")
/// to the `Cap` that taint analysis models. Returns `None` for categories taint /// to the `Cap` that taint analysis models. Returns `None` for categories taint
@ -5738,9 +5730,7 @@ impl TaintSuppressionCtx {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Pass 2 / singlefile: Full rule execution (AST queries + taint) // Pass 2 / singlefile: Full rule execution (AST queries + taint)
// ─────────────────────────────────────────────────────────────────────────────
/// Run all enabled analyses on pre-read bytes and return diagnostics. /// Run all enabled analyses on pre-read bytes and return diagnostics.
/// ///
@ -5816,9 +5806,7 @@ pub fn run_rules_on_file(
run_rules_on_bytes(&bytes, path, cfg, global_summaries, scan_root) run_rules_on_bytes(&bytes, path, cfg, global_summaries, scan_root)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Fused single-pass: extract summaries + run full analysis in one parse/CFG // Fused single-pass: extract summaries + run full analysis in one parse/CFG
// ─────────────────────────────────────────────────────────────────────────────
/// Result of a fused analysis pass: both function summaries and diagnostics. /// Result of a fused analysis pass: both function summaries and diagnostics.
pub struct FusedResult { pub struct FusedResult {
@ -6090,9 +6078,7 @@ pub fn analyse_file_fused(
}) })
} }
// ─────────────────────────────────────────────────────────────────────────────
// Text-based pattern scanning (non-tree-sitter files) // Text-based pattern scanning (non-tree-sitter files)
// ─────────────────────────────────────────────────────────────────────────────
/// Run text-based pattern scanners on files whose extension is not supported /// Run text-based pattern scanners on files whose extension is not supported
/// by tree-sitter. Currently handles `.ejs` templates. /// by tree-sitter. Currently handles `.ejs` templates.

View file

@ -15,9 +15,7 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::path::Path; use std::path::Path;
// ─────────────────────────────────────────────────────────────────────────────
// Baseline entry (stripped — no source code) // Baseline entry (stripped — no source code)
// ─────────────────────────────────────────────────────────────────────────────
/// A stripped baseline entry: only what is needed for cross-commit diffing. /// A stripped baseline entry: only what is needed for cross-commit diffing.
/// Contains no source code snippets. /// Contains no source code snippets.
@ -33,9 +31,7 @@ pub struct BaselineEntry {
pub rule_id: String, pub rule_id: String,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Transition enum // Transition enum
// ─────────────────────────────────────────────────────────────────────────────
/// How a finding's verdict changed between the baseline scan and the current /// How a finding's verdict changed between the baseline scan and the current
/// scan. /// scan.
@ -59,9 +55,7 @@ pub enum Transition {
FlippedNotConfirmed, FlippedNotConfirmed,
} }
// ─────────────────────────────────────────────────────────────────────────────
// VerdictDiffEntry // VerdictDiffEntry
// ─────────────────────────────────────────────────────────────────────────────
/// Per-finding verdict diff produced by comparing a baseline to a current scan. /// Per-finding verdict diff produced by comparing a baseline to a current scan.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -87,9 +81,7 @@ pub struct VerdictDiff {
pub entries: Vec<VerdictDiffEntry>, pub entries: Vec<VerdictDiffEntry>,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Load / write helpers // Load / write helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Load baseline entries from a file. /// Load baseline entries from a file.
/// ///
@ -164,9 +156,7 @@ pub fn write_baseline(path: &Path, diags: &[Diag]) -> crate::errors::NyxResult<(
}) })
} }
// ─────────────────────────────────────────────────────────────────────────────
// Diff computation // Diff computation
// ─────────────────────────────────────────────────────────────────────────────
fn classify_transition( fn classify_transition(
baseline: Option<VerifyStatus>, baseline: Option<VerifyStatus>,
@ -272,9 +262,7 @@ pub fn compute_verdict_diff(baseline: &[BaselineEntry], current: &[Diag]) -> Ver
VerdictDiff { entries } VerdictDiff { entries }
} }
// ─────────────────────────────────────────────────────────────────────────────
// CI gates // CI gates
// ─────────────────────────────────────────────────────────────────────────────
/// Gate: exit code 2 if any new `Confirmed` finding appears. /// Gate: exit code 2 if any new `Confirmed` finding appears.
/// ///
@ -320,9 +308,7 @@ pub fn check_gate(diff: &VerdictDiff, gate: &str) -> bool {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Console / JSON rendering // Console / JSON rendering
// ─────────────────────────────────────────────────────────────────────────────
fn status_str(s: Option<VerifyStatus>) -> &'static str { fn status_str(s: Option<VerifyStatus>) -> &'static str {
match s { match s {
@ -393,9 +379,7 @@ pub fn format_diff_console(diff: &VerdictDiff) -> String {
lines.join("\n") + "\n" lines.join("\n") + "\n"
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -20,9 +20,7 @@ use smallvec::SmallVec;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
// ─────────────────────────────────────────────────────────────────────────────
// Types // Types
// ─────────────────────────────────────────────────────────────────────────────
/// Metadata attached to each call-graph edge. /// Metadata attached to each call-graph edge.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -76,9 +74,7 @@ pub struct CallGraphAnalysis {
pub topo_scc_callee_first: Vec<usize>, pub topo_scc_callee_first: Vec<usize>,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Callee-name normalization // Callee-name normalization
// ─────────────────────────────────────────────────────────────────────────────
/// Extract the last segment of a qualified callee name for resolution. /// Extract the last segment of a qualified callee name for resolution.
/// ///
@ -164,9 +160,7 @@ pub(crate) fn callee_container_hint(raw: &str) -> &str {
"" ""
} }
// ─────────────────────────────────────────────────────────────────────────────
// Class / container → method index // Class / container → method index
// ─────────────────────────────────────────────────────────────────────────────
/// Per-language `(container, method_name)` → candidate [`FuncKey`] index. /// Per-language `(container, method_name)` → candidate [`FuncKey`] index.
/// ///
@ -374,9 +368,7 @@ impl TypeHierarchyIndex {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Call-graph construction // Call-graph construction
// ─────────────────────────────────────────────────────────────────────────────
/// Build the whole-program call graph from merged summaries. /// Build the whole-program call graph from merged summaries.
/// ///
@ -742,9 +734,7 @@ fn resolve_via_interop(
None None
} }
// ─────────────────────────────────────────────────────────────────────────────
// SCC / topological analysis // SCC / topological analysis
// ─────────────────────────────────────────────────────────────────────────────
/// Compute SCC decomposition and topological ordering of the call graph. /// Compute SCC decomposition and topological ordering of the call graph.
/// ///
@ -772,9 +762,7 @@ pub fn analyse(cg: &CallGraph) -> CallGraphAnalysis {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// File-level batch ordering // File-level batch ordering
// ─────────────────────────────────────────────────────────────────────────────
/// A batch of files at a single topological position, annotated with whether /// A batch of files at a single topological position, annotated with whether
/// any contributing SCC contains mutual recursion (len > 1) and whether any /// any contributing SCC contains mutual recursion (len > 1) and whether any
@ -1139,9 +1127,7 @@ pub(super) fn scc_file_batches<'a>(
(batches, orphans) (batches, orphans)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -121,9 +121,7 @@ fn extract_case_literal_text<'a>(case: Node<'a>, lang: &str, code: &'a [u8]) ->
} }
} }
// -------------------------------------------------------------------------
// Exception-source detection for try/catch wiring // Exception-source detection for try/catch wiring
// -------------------------------------------------------------------------
/// Returns true if this CFG node can implicitly raise an exception (calls). /// Returns true if this CFG node can implicitly raise an exception (calls).
/// Explicit throws are collected separately via `throw_targets`. /// Explicit throws are collected separately via `throw_targets`.
@ -190,9 +188,7 @@ pub(super) fn extract_catch_param_name<'a>(
} }
} }
// -------------------------------------------------------------------------
// Ruby begin/rescue/ensure handler // Ruby begin/rescue/ensure handler
// -------------------------------------------------------------------------
/// Builds CFG for Ruby's `begin`/`rescue`/`ensure` blocks (and `body_statement` /// Builds CFG for Ruby's `begin`/`rescue`/`ensure` blocks (and `body_statement`
/// with inline rescue). Ruby's `begin` has no `body` field, the try-body /// with inline rescue). Ruby's `begin` has no `body` field, the try-body
@ -442,9 +438,7 @@ pub(super) fn build_begin_rescue<'a>(
} }
} }
// -------------------------------------------------------------------------
// switch handler, multi-way dispatch with fallthrough // switch handler, multi-way dispatch with fallthrough
// -------------------------------------------------------------------------
/// True for AST kinds that wrap a single switch case body. /// True for AST kinds that wrap a single switch case body.
pub(super) fn is_switch_case_kind(kind: &str) -> bool { pub(super) fn is_switch_case_kind(kind: &str) -> bool {
@ -780,9 +774,7 @@ pub(super) fn build_switch<'a>(
exits exits
} }
// -------------------------------------------------------------------------
// try/catch/finally handler // try/catch/finally handler
// -------------------------------------------------------------------------
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub(super) fn build_try<'a>( pub(super) fn build_try<'a>(

View file

@ -388,9 +388,7 @@ fn js_catch_no_param_no_synthetic() {
); );
} }
// ─────────────────────────────────────────────────────────────────
// Ruby begin/rescue/ensure tests // Ruby begin/rescue/ensure tests
// ─────────────────────────────────────────────────────────────────
#[test] #[test]
fn ruby_begin_rescue_has_exception_edges() { fn ruby_begin_rescue_has_exception_edges() {
@ -540,9 +538,7 @@ fn ruby_multiple_rescue_clauses() {
} }
} }
// ─────────────────────────────────────────────────────────────────
// Short-circuit evaluation tests // Short-circuit evaluation tests
// ─────────────────────────────────────────────────────────────────
/// Helper: collect all If nodes from the CFG. /// Helper: collect all If nodes from the CFG.
fn if_nodes(cfg: &Cfg) -> Vec<NodeIndex> { fn if_nodes(cfg: &Cfg) -> Vec<NodeIndex> {
@ -2008,10 +2004,8 @@ fn local_summary_callees_have_distinct_ordinals() {
assert_ne!(ord0, ord1, "ordinals must differ across sites"); assert_ne!(ord0, ord1, "ordinals must differ across sites");
} }
// ─────────────────────────────────────────────────────────────────────
// Anonymous function body naming via syntactic context // Anonymous function body naming via syntactic context
// (derive_anon_fn_name_from_context coverage) // (derive_anon_fn_name_from_context coverage)
// ─────────────────────────────────────────────────────────────────────
fn js_body_names(src: &[u8]) -> Vec<String> { fn js_body_names(src: &[u8]) -> Vec<String> {
let ts_lang = Language::from(tree_sitter_javascript::LANGUAGE); let ts_lang = Language::from(tree_sitter_javascript::LANGUAGE);
@ -2531,9 +2525,7 @@ fn pointer_disabled_skips_subscript_synthesis() {
}); });
} }
// ─────────────────────────────────────────────────────────────────
// Gap-filling: switch / for / do-while / nested loops / re-throw // Gap-filling: switch / for / do-while / nested loops / re-throw
// ─────────────────────────────────────────────────────────────────
/// JS `switch` should produce one synthetic dispatch `If` node per /// JS `switch` should produce one synthetic dispatch `If` node per
/// case (default excluded when at the tail), plus True edges into /// case (default excluded when at the tail), plus True edges into
@ -2908,12 +2900,10 @@ fn js_empty_function_body_well_formed() {
} }
} }
// ─────────────────────────────────────────────────────────────────────
// Loop CFG structure: every loop variant must produce a Loop header // Loop CFG structure: every loop variant must produce a Loop header
// with at least one Back edge that targets that header. Without these // with at least one Back edge that targets that header. Without these
// invariants the SSA loop-induction-variable phi placement is wrong // invariants the SSA loop-induction-variable phi placement is wrong
// and the abstract-interp widening points are missed. // and the abstract-interp widening points are missed.
// ─────────────────────────────────────────────────────────────────────
fn loop_headers(cfg: &Cfg) -> Vec<NodeIndex> { fn loop_headers(cfg: &Cfg) -> Vec<NodeIndex> {
cfg.node_indices() cfg.node_indices()
@ -3998,9 +3988,7 @@ function outer(obj, x, y) {
assert_eq!(mline, 4, "obj.method(x) on line 4"); assert_eq!(mline, 4, "obj.method(x) on line 4");
} }
// ─────────────────────────────────────────────────────────────────
// Constant-branch fold: CondArith capture + evaluation // Constant-branch fold: CondArith capture + evaluation
// ─────────────────────────────────────────────────────────────────
/// `CondArith::eval`/`eval_bool` must fold the two OWASP-Benchmark /// `CondArith::eval`/`eval_bool` must fold the two OWASP-Benchmark
/// arithmetic guard shapes to a definite boolean, using integer /// arithmetic guard shapes to a definite boolean, using integer

View file

@ -10,9 +10,7 @@ use petgraph::graph::NodeIndex;
use smallvec::SmallVec; use smallvec::SmallVec;
use tree_sitter::Node; use tree_sitter::Node;
// -------------------------------------------------------------------------
// Short-circuit boolean operator helpers // Short-circuit boolean operator helpers
// -------------------------------------------------------------------------
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub(super) enum BoolOp { pub(super) enum BoolOp {

View file

@ -90,9 +90,7 @@ fn collect_ts_type_alias_local_collections(root: Node<'_>, code: &[u8], out: &mu
}); });
} }
// ─────────────────────────────────────────────────────────────────────
// Java // Java
// ─────────────────────────────────────────────────────────────────────
/// Walk the AST for `class_declaration` nodes whose body contains /// Walk the AST for `class_declaration` nodes whose body contains
/// `field_declaration`s with classifiable types. Only class-level /// `field_declaration`s with classifiable types. Only class-level
@ -144,9 +142,7 @@ fn collect_java(root: Node<'_>, code: &[u8], out: &mut HashMap<String, DtoFields
}); });
} }
// ─────────────────────────────────────────────────────────────────────
// TypeScript / JavaScript // TypeScript / JavaScript
// ─────────────────────────────────────────────────────────────────────
/// Walk for `interface_declaration` and `class_declaration` nodes. /// Walk for `interface_declaration` and `class_declaration` nodes.
/// Interfaces with `property_signature` children and classes with /// Interfaces with `property_signature` children and classes with
@ -224,9 +220,7 @@ fn extract_ts_property<'a>(node: Node<'a>, code: &'a [u8]) -> Option<(String, Ty
Some((field_name, kind)) Some((field_name, kind))
} }
// ─────────────────────────────────────────────────────────────────────
// Rust // Rust
// ─────────────────────────────────────────────────────────────────────
/// Walk for `struct_item` nodes whose body lists named fields. /// Walk for `struct_item` nodes whose body lists named fields.
fn collect_rust(root: Node<'_>, code: &[u8], out: &mut HashMap<String, DtoFields>) { fn collect_rust(root: Node<'_>, code: &[u8], out: &mut HashMap<String, DtoFields>) {
@ -276,9 +270,7 @@ fn collect_rust(root: Node<'_>, code: &[u8], out: &mut HashMap<String, DtoFields
}); });
} }
// ─────────────────────────────────────────────────────────────────────
// Python (Pydantic) // Python (Pydantic)
// ─────────────────────────────────────────────────────────────────────
/// Walk for `class_definition` nodes whose superclass list contains /// Walk for `class_definition` nodes whose superclass list contains
/// `BaseModel` / `pydantic.BaseModel`. Each `expression_statement` in /// `BaseModel` / `pydantic.BaseModel`. Each `expression_statement` in
@ -360,9 +352,7 @@ fn python_inherits_basemodel<'a>(class_node: Node<'a>, code: &'a [u8]) -> bool {
false false
} }
// ─────────────────────────────────────────────────────────────────────
// Walk helper // Walk helper
// ─────────────────────────────────────────────────────────────────────
fn walk<'a, F: FnMut(Node<'a>)>(node: Node<'a>, f: &mut F) { fn walk<'a, F: FnMut(Node<'a>)>(node: Node<'a>, f: &mut F) {
f(node); f(node);

View file

@ -4,9 +4,7 @@ use crate::labels::{DataLabel, Kind, classify, lookup};
use smallvec::SmallVec; use smallvec::SmallVec;
use tree_sitter::Node; use tree_sitter::Node;
// -------------------------------------------------------------------------
// Utility helpers // Utility helpers
// -------------------------------------------------------------------------
/// Return the text of a node. /// Return the text of a node.
#[inline] #[inline]

View file

@ -54,9 +54,7 @@ pub(crate) fn collect_hierarchy_edges(
acc acc
} }
// ─────────────────────────────────────────────────────────────────────
// Java // Java
// ─────────────────────────────────────────────────────────────────────
fn collect_java<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) { fn collect_java<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) {
walk(root, &mut |node| { walk(root, &mut |node| {
@ -146,9 +144,7 @@ fn type_identifier_text(n: Node<'_>, code: &[u8]) -> Option<String> {
} }
} }
// ─────────────────────────────────────────────────────────────────────
// Rust // Rust
// ─────────────────────────────────────────────────────────────────────
/// Walk for `impl_item` nodes and emit edges from the concrete type to /// Walk for `impl_item` nodes and emit edges from the concrete type to
/// the trait being implemented. Inherent impls (`impl Foo {}`) emit /// the trait being implemented. Inherent impls (`impl Foo {}`) emit
@ -199,9 +195,7 @@ fn rust_path_leaf(n: Node<'_>, code: &[u8]) -> Option<String> {
} }
} }
// ─────────────────────────────────────────────────────────────────────
// TypeScript / JavaScript // TypeScript / JavaScript
// ─────────────────────────────────────────────────────────────────────
fn collect_ts<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) { fn collect_ts<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) {
walk(root, &mut |node| { walk(root, &mut |node| {
@ -268,9 +262,7 @@ fn collect_ts_heritage<F: FnMut(String, String)>(
} }
} }
// ─────────────────────────────────────────────────────────────────────
// Python // Python
// ─────────────────────────────────────────────────────────────────────
fn collect_python<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) { fn collect_python<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) {
walk(root, &mut |node| { walk(root, &mut |node| {
@ -314,9 +306,7 @@ fn python_base_text(n: Node<'_>, code: &[u8]) -> Option<String> {
} }
} }
// ─────────────────────────────────────────────────────────────────────
// Ruby // Ruby
// ─────────────────────────────────────────────────────────────────────
fn collect_ruby<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) { fn collect_ruby<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) {
walk(root, &mut |node| { walk(root, &mut |node| {
@ -345,9 +335,7 @@ fn collect_ruby<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mu
}); });
} }
// ─────────────────────────────────────────────────────────────────────
// PHP // PHP
// ─────────────────────────────────────────────────────────────────────
fn collect_php<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) { fn collect_php<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) {
walk(root, &mut |node| { walk(root, &mut |node| {
@ -382,9 +370,7 @@ fn collect_php<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut
}); });
} }
// ─────────────────────────────────────────────────────────────────────
// C++ // C++
// ─────────────────────────────────────────────────────────────────────
fn collect_cpp<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) { fn collect_cpp<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut F) {
walk(root, &mut |node| { walk(root, &mut |node| {
@ -419,9 +405,7 @@ fn collect_cpp<F: FnMut(String, String)>(root: Node<'_>, code: &[u8], push: &mut
}); });
} }
// ─────────────────────────────────────────────────────────────────────
// Helpers // Helpers
// ─────────────────────────────────────────────────────────────────────
fn walk<'a, F: FnMut(Node<'a>)>(node: Node<'a>, f: &mut F) { fn walk<'a, F: FnMut(Node<'a>)>(node: Node<'a>, f: &mut F) {
f(node); f(node);

View file

@ -135,9 +135,7 @@ fn map_fs_module_to_promises(module: &str) -> Option<String> {
} }
} }
// -------------------------------------------------------------------------
// Import binding extraction // Import binding extraction
// -------------------------------------------------------------------------
/// Walk the top-level AST nodes and collect import alias bindings: /// Walk the top-level AST nodes and collect import alias bindings:
/// ///
@ -615,6 +613,4 @@ fn scoped_identifier_matches(node: Node, code: &[u8], crate_prefix: &str, leaf:
(Some(p), Some(l)) if p == crate_prefix && l == leaf) (Some(p), Some(l)) if p == crate_prefix && l == leaf)
} }
// -------------------------------------------------------------------------
// === PUBLIC ENTRY POINT ================================================= // === PUBLIC ENTRY POINT =================================================
// -------------------------------------------------------------------------

View file

@ -955,9 +955,7 @@ pub struct LocalFuncSummary {
pub type Cfg = Graph<NodeInfo, EdgeKind>; pub type Cfg = Graph<NodeInfo, EdgeKind>;
pub type FuncSummaries = HashMap<FuncKey, LocalFuncSummary>; pub type FuncSummaries = HashMap<FuncKey, LocalFuncSummary>;
// -------------------------------------------------------------------------
// Per-body CFG types // Per-body CFG types
// -------------------------------------------------------------------------
/// Opaque identifier for an executable body within a file. /// Opaque identifier for an executable body within a file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
@ -5075,10 +5073,8 @@ fn apply_arg_source_bindings(
} }
} }
// -------------------------------------------------------------------------
// The recursive *workhorse* that converts an AST node into a CFG slice. // The recursive *workhorse* that converts an AST node into a CFG slice.
// Returns the set of *exit* nodes that need to be wired further. // Returns the set of *exit* nodes that need to be wired further.
// -------------------------------------------------------------------------
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub(super) fn build_sub<'a>( pub(super) fn build_sub<'a>(
ast: Node<'a>, ast: Node<'a>,
@ -5099,9 +5095,7 @@ pub(super) fn build_sub<'a>(
current_body_id: BodyId, current_body_id: BodyId,
) -> Vec<NodeIndex> { ) -> Vec<NodeIndex> {
match lookup(lang, ast.kind()) { match lookup(lang, ast.kind()) {
// ─────────────────────────────────────────────────────────────────
// IF/ELSE: two branches that remerge afterwards // IF/ELSE: two branches that remerge afterwards
// ─────────────────────────────────────────────────────────────────
Kind::If => { Kind::If => {
// Some grammars (Go `if init; cond {}`, sibling C-style forms) // Some grammars (Go `if init; cond {}`, sibling C-style forms)
// attach an init / "initializer" subtree that runs before the // attach an init / "initializer" subtree that runs before the
@ -5383,9 +5377,7 @@ pub(super) fn build_sub<'a>(
} }
} }
// ─────────────────────────────────────────────────────────────────
// WHILE / FOR: classic loop with a back edge. // WHILE / FOR: classic loop with a back edge.
// ─────────────────────────────────────────────────────────────────
Kind::While | Kind::For => { Kind::While | Kind::For => {
let header = push_node( let header = push_node(
g, g,
@ -5527,9 +5519,7 @@ pub(super) fn build_sub<'a>(
} }
} }
// ─────────────────────────────────────────────────────────────────
// Control-flow sinks (return / break / continue). // Control-flow sinks (return / break / continue).
// ─────────────────────────────────────────────────────────────────
Kind::Return => { Kind::Return => {
if has_call_descendant(ast, lang) { if has_call_descendant(ast, lang) {
// Return-call bug fix: emit a Call node BEFORE the Return so // Return-call bug fix: emit a Call node BEFORE the Return so
@ -5825,9 +5815,7 @@ pub(super) fn build_sub<'a>(
current_body_id, current_body_id,
), ),
// ─────────────────────────────────────────────────────────────────
// BLOCK: statements execute sequentially // BLOCK: statements execute sequentially
// ─────────────────────────────────────────────────────────────────
Kind::SourceFile | Kind::Block => { Kind::SourceFile | Kind::Block => {
// Ruby body_statement with rescue/ensure = implicit begin/rescue // Ruby body_statement with rescue/ensure = implicit begin/rescue
if lang == "ruby" && ast.kind() == "body_statement" { if lang == "ruby" && ast.kind() == "body_statement" {
@ -6655,9 +6643,7 @@ pub(super) fn build_sub<'a>(
analysis_rules, analysis_rules,
), ),
// ─────────────────────────────────────────────────────────────────
// Every other node = simple sequential statement // Every other node = simple sequential statement
// ─────────────────────────────────────────────────────────────────
_ => { _ => {
// React JSX `dangerouslySetInnerHTML={{__html: x}}` synthesis // React JSX `dangerouslySetInnerHTML={{__html: x}}` synthesis
// (Phase 06): handles arrow-bodied components like // (Phase 06): handles arrow-bodied components like
@ -7145,21 +7131,5 @@ pub(crate) fn export_summaries(
.collect() .collect()
} }
// pub(crate) fn dump_cfg(g: &Cfg) {
// debug!(target: "taint", "CFG DUMP: nodes = {}, edges = {}", g.node_count(), g.edge_count());
// for idx in g.node_indices() {
// debug!(target: "taint", " node {:>3}: {:?}", idx.index(), g[idx]);
// }
// for e in g.edge_references() {
// debug!(
// target: "taint",
// " edge {:>3} → {:<3} ({:?})",
// e.source().index(),
// e.target().index(),
// e.weight()
// );
// }
// }
#[cfg(test)] #[cfg(test)]
mod cfg_tests; mod cfg_tests;

View file

@ -924,9 +924,7 @@ pub fn handle(
Ok(()) Ok(())
} }
// --------------------------------------------------------------------------------------------
// Shared post-processing helpers // Shared post-processing helpers
// --------------------------------------------------------------------------------------------
/// Assign confidence, rank, and truncate diagnostics. /// Assign confidence, rank, and truncate diagnostics.
pub(crate) fn post_process_diags(diags: &mut Vec<Diag>, cfg: &Config) { pub(crate) fn post_process_diags(diags: &mut Vec<Diag>, cfg: &Config) {
@ -1978,9 +1976,7 @@ fn run_topo_batches(
result result
} }
// --------------------------------------------------------------------------------------------
// Two-pass scanning (no index) // Two-pass scanning (no index)
// --------------------------------------------------------------------------------------------
/// Walk the filesystem and perform a two-pass scan: /// Walk the filesystem and perform a two-pass scan:
/// ///
@ -2487,9 +2483,7 @@ pub(crate) fn scan_filesystem_with_observer(
Ok((diags, surface_map)) Ok((diags, surface_map))
} }
// --------------------------------------------------------------------------------------------
// Two-pass scanning (with index) // Two-pass scanning (with index)
// --------------------------------------------------------------------------------------------
/// Indexed two-pass scan: /// Indexed two-pass scan:
/// ///
@ -3352,9 +3346,7 @@ pub fn scan_with_index_parallel_observer(
Ok(diags) Ok(diags)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Low-noise prioritization pipeline // Low-noise prioritization pipeline
// ─────────────────────────────────────────────────────────────────────────────
/// Rules eligible for rollup grouping (high-frequency, low-signal patterns). /// Rules eligible for rollup grouping (high-frequency, low-signal patterns).
const ROLLUP_RULES: &[&str] = &[ const ROLLUP_RULES: &[&str] = &[
@ -3610,9 +3602,7 @@ fn apply_low_budgets(
stats.low_budget_dropped = before - diags.len(); stats.low_budget_dropped = before - diags.len();
} }
// ─────────────────────────────────────────────────────────────────────────────
// Inline suppression application // Inline suppression application
// ─────────────────────────────────────────────────────────────────────────────
/// Apply inline `nyx:ignore` / `nyx:ignore-next-line` suppressions to `diags`. /// Apply inline `nyx:ignore` / `nyx:ignore-next-line` suppressions to `diags`.
/// ///
@ -3646,9 +3636,7 @@ fn apply_suppressions(diags: &mut [Diag]) {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// dynamic verification summary tests // dynamic verification summary tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod dynamic_summary_tests { mod dynamic_summary_tests {
@ -3698,9 +3686,7 @@ mod dynamic_summary_tests {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// deduplicate_taint_flows tests // deduplicate_taint_flows tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod dedup_taint_flow_tests { mod dedup_taint_flow_tests {
@ -4268,9 +4254,7 @@ fn severity_filter_applied_at_output_stage() {
assert_eq!(filtered[0].path, "src/main.rs"); assert_eq!(filtered[0].path, "src/main.rs");
} }
// ─────────────────────────────────────────────────────────────────────────────
// Prioritization pipeline tests // Prioritization pipeline tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod prioritize_tests { mod prioritize_tests {

View file

@ -207,9 +207,7 @@ fn collect_files(root: &Path, config: &Config) -> NyxResult<Vec<PathBuf>> {
Ok(out) Ok(out)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Text rendering // Text rendering
// ─────────────────────────────────────────────────────────────────────────────
/// Produce a human-readable tree. Files appear as top-level headers; /// Produce a human-readable tree. Files appear as top-level headers;
/// each entry-point sits under its host file with its reach summary /// each entry-point sits under its host file with its reach summary
@ -434,9 +432,7 @@ fn es_kind_str(k: ExternalServiceKind) -> &'static str {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// DOT / SVG rendering // DOT / SVG rendering
// ─────────────────────────────────────────────────────────────────────────────
pub fn render_dot(map: &SurfaceMap) -> String { pub fn render_dot(map: &SurfaceMap) -> String {
let mut out = String::new(); let mut out = String::new();

View file

@ -2166,9 +2166,7 @@ pub mod index {
.collect::<Result<_, _>>()?) .collect::<Result<_, _>>()?)
} }
// -------------------------------------------------------------------------
// Scan persistence // Scan persistence
// -------------------------------------------------------------------------
/// Insert a new scan record. /// Insert a new scan record.
pub fn insert_scan(&self, record: &ScanRecord) -> NyxResult<()> { pub fn insert_scan(&self, record: &ScanRecord) -> NyxResult<()> {
@ -2434,9 +2432,7 @@ pub mod index {
Ok(rows) Ok(rows)
} }
// -------------------------------------------------------------------------
// Triage state management // Triage state management
// -------------------------------------------------------------------------
/// Get the triage state for a single finding fingerprint. /// Get the triage state for a single finding fingerprint.
/// Returns (state, note, updated_at) or None if no triage state exists. /// Returns (state, note, updated_at) or None if no triage state exists.
@ -2816,9 +2812,7 @@ pub mod index {
Ok(count > 0) Ok(count > 0)
} }
// -------------------------------------------------------------------------
// Maintenance utilities // Maintenance utilities
// -------------------------------------------------------------------------
pub fn clear(&self) -> NyxResult<()> { pub fn clear(&self) -> NyxResult<()> {
self.c().execute_batch( self.c().execute_batch(
r#" r#"
@ -2843,9 +2837,7 @@ pub mod index {
Ok(()) Ok(())
} }
// -------------------------------------------------------------------------
// Helpers // Helpers
// -------------------------------------------------------------------------
#[cfg(test)] #[cfg(test)]
fn digest_file(path: &Path) -> NyxResult<Vec<u8>> { fn digest_file(path: &Path) -> NyxResult<Vec<u8>> {
let mut hasher = blake3::Hasher::new(); let mut hasher = blake3::Hasher::new();

View file

@ -83,6 +83,14 @@ pub fn syscall_number(name: &str) -> Option<u32> {
"getgid" => 104, "getgid" => 104,
"geteuid" => 107, "geteuid" => 107,
"getegid" => 108, "getegid" => 108,
"setuid" => 105,
"setgid" => 106,
"setreuid" => 113,
"setregid" => 114,
"setresuid" => 117,
"setresgid" => 119,
"setfsuid" => 122,
"setfsgid" => 123,
"sigaltstack" => 131, "sigaltstack" => 131,
"setrlimit" => 160, "setrlimit" => 160,
"arch_prctl" => 158, "arch_prctl" => 158,
@ -245,6 +253,14 @@ pub fn syscall_number(name: &str) -> Option<u32> {
"geteuid" => 175, "geteuid" => 175,
"getgid" => 176, "getgid" => 176,
"getegid" => 177, "getegid" => 177,
"setregid" => 143,
"setgid" => 144,
"setreuid" => 145,
"setuid" => 146,
"setresuid" => 147,
"setresgid" => 149,
"setfsuid" => 151,
"setfsgid" => 152,
"socket" => 198, "socket" => 198,
"socketpair" => 199, "socketpair" => 199,
"bind" => 200, "bind" => 200,

View file

@ -191,9 +191,7 @@ pub fn detect_entries_in_file(
} }
} }
// ─────────────────────────────────────────────────────────────────────
// JS / TS — Next.js (Phase 10) + Express (Phase 16) // JS / TS — Next.js (Phase 10) + Express (Phase 16)
// ─────────────────────────────────────────────────────────────────────
fn detect_js_ts(root: Node<'_>, bytes: &[u8], path: &Path) -> HashMap<(usize, usize), EntryKind> { fn detect_js_ts(root: Node<'_>, bytes: &[u8], path: &Path) -> HashMap<(usize, usize), EntryKind> {
let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new(); let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new();
@ -727,9 +725,7 @@ fn express_receiver_text_matches(object: Node, bytes: &[u8]) -> bool {
} }
} }
// ─────────────────────────────────────────────────────────────────────
// Python — Django / FastAPI / Flask // Python — Django / FastAPI / Flask
// ─────────────────────────────────────────────────────────────────────
fn detect_python(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> { fn detect_python(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new(); let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new();
@ -895,9 +891,7 @@ fn enclosing_python_class<'a>(node: Node<'a>) -> Option<Node<'a>> {
None None
} }
// ─────────────────────────────────────────────────────────────────────
// Java — Spring + JAX-RS // Java — Spring + JAX-RS
// ─────────────────────────────────────────────────────────────────────
fn detect_java(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> { fn detect_java(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new(); let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new();
@ -1016,9 +1010,7 @@ fn http_method_from_request_method_text(node: Node, bytes: &[u8]) -> Option<Http
None None
} }
// ─────────────────────────────────────────────────────────────────────
// Ruby — Rails + Sinatra // Ruby — Rails + Sinatra
// ─────────────────────────────────────────────────────────────────────
fn detect_ruby(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> { fn detect_ruby(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new(); let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new();
@ -1108,9 +1100,7 @@ where
} }
} }
// ─────────────────────────────────────────────────────────────────────
// Rust — axum / actix-web / rocket // Rust — axum / actix-web / rocket
// ─────────────────────────────────────────────────────────────────────
fn detect_rust(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> { fn detect_rust(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new(); let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new();
@ -1252,9 +1242,7 @@ fn rust_signature_has_axum_extractor(func: Node, bytes: &[u8]) -> bool {
needles.iter().any(|n| text.contains(n)) needles.iter().any(|n| text.contains(n))
} }
// ─────────────────────────────────────────────────────────────────────
// Go — net/http + gin / echo / chi // Go — net/http + gin / echo / chi
// ─────────────────────────────────────────────────────────────────────
fn detect_go(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> { fn detect_go(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new(); let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new();
@ -1305,9 +1293,7 @@ fn go_function_entry_kind(func: Node, bytes: &[u8]) -> Option<EntryKind> {
None None
} }
// ─────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -14,9 +14,7 @@ use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
// ─────────────────────────────────────────────────────────────────────────────
// Confidence // Confidence
// ─────────────────────────────────────────────────────────────────────────────
/// Confidence level for a diagnostic finding. /// Confidence level for a diagnostic finding.
/// ///
@ -54,9 +52,7 @@ impl FromStr for Confidence {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Flow Steps // Flow Steps
// ─────────────────────────────────────────────────────────────────────────────
/// The kind of operation at a flow step. /// The kind of operation at a flow step.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -116,9 +112,7 @@ pub struct FlowStep {
pub is_cross_file: bool, pub is_cross_file: bool,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Symbolic verdict // Symbolic verdict
// ─────────────────────────────────────────────────────────────────────────────
/// Symbolic verification verdict for a taint path. /// Symbolic verification verdict for a taint path.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
@ -156,9 +150,7 @@ pub struct SymbolicVerdict {
pub cutoff_notes: Vec<String>, pub cutoff_notes: Vec<String>,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Dynamic verification verdict types (always present; not feature-gated) // Dynamic verification verdict types (always present; not feature-gated)
// ─────────────────────────────────────────────────────────────────────────────
/// Why dynamic verification cannot be attempted for a finding. /// Why dynamic verification cannot be attempted for a finding.
/// ///
@ -960,9 +952,7 @@ pub struct VerifyResult {
pub hardening_outcome: Option<HardeningSummary>, pub hardening_outcome: Option<HardeningSummary>,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Evidence // Evidence
// ─────────────────────────────────────────────────────────────────────────────
/// Structured evidence for a diagnostic finding. /// Structured evidence for a diagnostic finding.
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[derive(Debug, Clone, Default, Serialize, Deserialize)]
@ -1108,9 +1098,7 @@ pub struct StateEvidence {
pub to_state: String, pub to_state: String,
} }
// ─────────────────────────────────────────────────────────────────────────────
// compute_confidence // compute_confidence
// ─────────────────────────────────────────────────────────────────────────────
/// Derive a confidence level for `diag` based on its rule ID, severity, /// Derive a confidence level for `diag` based on its rule ID, severity,
/// evidence, and analysis kind. /// evidence, and analysis kind.
@ -1422,9 +1410,7 @@ fn cap_specificity_score(notes: &[String]) -> i32 {
0 0
} }
// ─────────────────────────────────────────────────────────────────────────────
// Explanation & Confidence Limiters // Explanation & Confidence Limiters
// ─────────────────────────────────────────────────────────────────────────────
/// Generate a human-readable explanation of a taint finding from its evidence. /// Generate a human-readable explanation of a taint finding from its evidence.
pub fn generate_explanation(diag: &Diag) -> Option<String> { pub fn generate_explanation(diag: &Diag) -> Option<String> {
@ -1592,9 +1578,7 @@ pub fn compute_confidence_limiters(diag: &Diag) -> Vec<String> {
limiters limiters
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -13,9 +13,7 @@ use std::collections::BTreeMap;
/// Default maximum line width when terminal size is unknown. /// Default maximum line width when terminal size is unknown.
const DEFAULT_WIDTH: usize = 100; const DEFAULT_WIDTH: usize = 100;
// ─────────────────────────────────────────────────────────────────────────────
// Public API // Public API
// ─────────────────────────────────────────────────────────────────────────────
/// Render all diagnostics as grouped, formatted console output with a summary. /// Render all diagnostics as grouped, formatted console output with a summary.
/// ///
@ -190,9 +188,7 @@ pub fn shorten_callee(s: &str) -> String {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Welcome screen // Welcome screen
// ─────────────────────────────────────────────────────────────────────────────
/// Render the branded welcome screen shown when `nyx` is invoked with no arguments. /// Render the branded welcome screen shown when `nyx` is invoked with no arguments.
pub fn render_welcome() -> String { pub fn render_welcome() -> String {
@ -258,9 +254,7 @@ const LOGO: &[&str] = &[
r"╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝", r"╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝",
]; ];
// ─────────────────────────────────────────────────────────────────────────────
// Internal rendering // Internal rendering
// ─────────────────────────────────────────────────────────────────────────────
/// Indentation for body/evidence lines (spaces). /// Indentation for body/evidence lines (spaces).
const BODY_INDENT: usize = 6; const BODY_INDENT: usize = 6;
@ -670,9 +664,7 @@ fn severity_tag(sev: Severity) -> String {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Text utilities // Text utilities
// ─────────────────────────────────────────────────────────────────────────────
/// Collapse spacing artefacts in method chains. /// Collapse spacing artefacts in method chains.
/// ///
@ -775,9 +767,7 @@ fn capitalize_first(s: &str) -> String {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -11,13 +11,8 @@ use std::time::Instant;
use tracing_subscriber::fmt::time; use tracing_subscriber::fmt::time;
use tracing_subscriber::prelude::*; use tracing_subscriber::prelude::*;
use tracing_subscriber::{EnvFilter, Registry, fmt as tracing_fmt}; use tracing_subscriber::{EnvFilter, Registry, fmt as tracing_fmt};
// use tracing_appender::rolling::{RollingFileAppender, Rotation};
// use tracing_appender::non_blocking;
fn init_tracing(quiet: bool) { fn init_tracing(quiet: bool) {
// let file_appender = RollingFileAppender::new(Rotation::HOURLY, "logs", "nyx-scanner.log");
// let (file_writer, guard) = non_blocking(file_appender);
let filter = if quiet { let filter = if quiet {
EnvFilter::new("off") EnvFilter::new("off")
} else { } else {
@ -30,11 +25,6 @@ fn init_tracing(quiet: bool) {
.with_thread_ids(true) .with_thread_ids(true)
.with_timer(time::UtcTime::rfc_3339()); .with_timer(time::UtcTime::rfc_3339());
// let file_layer = fmt::layer()
// .with_writer(file_writer)
// .without_time()
// .json();
Registry::default().with(filter).with(fmt_layer).init(); Registry::default().with(filter).with(fmt_layer).init();
} }

View file

@ -234,9 +234,7 @@ pub fn rank_diags(diags: &mut [Diag]) {
}); });
} }
// ─────────────────────────────────────────────────────────────────────────────
// Scoring helpers // Scoring helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Rank delta from the dynamic verification verdict. /// Rank delta from the dynamic verification verdict.
/// ///
@ -394,9 +392,7 @@ fn state_finding_bonus(rule_id: &str) -> f64 {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -52,9 +52,7 @@ impl RustUseMap {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Module path derivation // Module path derivation
// ─────────────────────────────────────────────────────────────────────────────
/// Find the crate root by walking up from `file_path` looking for `Cargo.toml`. /// Find the crate root by walking up from `file_path` looking for `Cargo.toml`.
/// ///
@ -137,9 +135,7 @@ pub fn derive_module_path(file_path: &Path, scan_root: Option<&Path>) -> Option<
Some(path) Some(path)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Use-declaration parsing // Use-declaration parsing
// ─────────────────────────────────────────────────────────────────────────────
/// Parse every top-level `use_declaration` of a Rust source tree into a /// Parse every top-level `use_declaration` of a Rust source tree into a
/// [`RustUseMap`]. /// [`RustUseMap`].
@ -328,9 +324,7 @@ fn join_segments(prefix: &[String], suffix: &[String]) -> String {
all.join("::") all.join("::")
} }
// ─────────────────────────────────────────────────────────────────────────────
// Resolution helpers // Resolution helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Resolve a Rust callee `(qualifier, name)` against a use map. /// Resolve a Rust callee `(qualifier, name)` against a use map.
/// ///
@ -389,9 +383,7 @@ pub fn split_module_and_name(qualified: &str) -> (String, String) {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -33,9 +33,7 @@ use serde::Serialize;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::path::Path; use std::path::Path;
// ─────────────────────────────────────────────────────────────────────────────
// Line-number helper // Line-number helper
// ─────────────────────────────────────────────────────────────────────────────
/// Convert a byte offset to a 1-based line number. /// Convert a byte offset to a 1-based line number.
fn byte_offset_to_line(bytes: &[u8], offset: usize) -> usize { fn byte_offset_to_line(bytes: &[u8], offset: usize) -> usize {
@ -43,9 +41,7 @@ fn byte_offset_to_line(bytes: &[u8], offset: usize) -> usize {
bytes[..offset].iter().filter(|&&b| b == b'\n').count() + 1 bytes[..offset].iter().filter(|&&b| b == b'\n').count() + 1
} }
// ─────────────────────────────────────────────────────────────────────────────
// Cap → human-readable names // Cap → human-readable names
// ─────────────────────────────────────────────────────────────────────────────
fn cap_names(c: Cap) -> Vec<String> { fn cap_names(c: Cap) -> Vec<String> {
let mut names = Vec::new(); let mut names = Vec::new();
@ -96,9 +92,7 @@ fn label_str(l: &DataLabel) -> String {
} }
} }
// ═════════════════════════════════════════════════════════════════════════════
// View-model types // View-model types
// ═════════════════════════════════════════════════════════════════════════════
// ── Function list ──────────────────────────────────────────────────────────── // ── Function list ────────────────────────────────────────────────────────────
@ -1397,9 +1391,7 @@ fn route_view(r: &RouteRegistration, _bytes: &[u8]) -> AuthRouteView {
} }
} }
// ═════════════════════════════════════════════════════════════════════════════
// On-demand analysis pipeline // On-demand analysis pipeline
// ═════════════════════════════════════════════════════════════════════════════
/// Result of parsing + CFG construction for a single file. /// Result of parsing + CFG construction for a single file.
pub struct FileAnalysis { pub struct FileAnalysis {

View file

@ -315,11 +315,9 @@ mod tests {
} }
} }
// ─────────────────────────────────────────────────────────────────
// Skip-conditions: copy-prop must NOT erase semantic info attached // Skip-conditions: copy-prop must NOT erase semantic info attached
// to a copy's CFG node. These guard the three early-exits in // to a copy's CFG node. These guard the three early-exits in
// `copy_propagate`: labels, numeric-length, and string_prefix. // `copy_propagate`: labels, numeric-length, and string_prefix.
// ─────────────────────────────────────────────────────────────────
/// Build a single-block SSA body containing /// Build a single-block SSA body containing
/// v0 = Const, v1 = Assign(v0) /// v0 = Const, v1 = Assign(v0)

View file

@ -2227,9 +2227,7 @@ fn rename_variables(
) )
} }
// ─────────────────────────────────────────────────────────────────────────────
// Debug invariant checkers // Debug invariant checkers
// ─────────────────────────────────────────────────────────────────────────────
/// Verify BFS block ordering: every non-entry, non-orphan block must have at /// Verify BFS block ordering: every non-entry, non-orphan block must have at
/// least one predecessor with a smaller block ID. /// least one predecessor with a smaller block ID.
@ -3532,9 +3530,7 @@ mod tests {
} }
} }
// ─────────────────────────────────────────────────────────────────
// FieldProj chain lowering tests // FieldProj chain lowering tests
// ─────────────────────────────────────────────────────────────────
// //
// These tests pin the contract that `try_lower_field_proj_chain` // These tests pin the contract that `try_lower_field_proj_chain`
// emits a `FieldProj` chain for chained-receiver method calls // emits a `FieldProj` chain for chained-receiver method calls
@ -4370,11 +4366,9 @@ mod tests {
); );
} }
// ─────────────────────────────────────────────────────────────────
// SSA edge cases: loop induction, multi-variable phis, multiple // SSA edge cases: loop induction, multi-variable phis, multiple
// returns, switch-cases, and shadowing. These plug holes in the // returns, switch-cases, and shadowing. These plug holes in the
// dominator-frontier / variable-renaming coverage. // dominator-frontier / variable-renaming coverage.
// ─────────────────────────────────────────────────────────────────
/// Loop induction variable: `x = x + 1` inside a loop is the /// Loop induction variable: `x = x + 1` inside a loop is the
/// canonical SSA challenge, the body uses `x` then redefines it, /// canonical SSA challenge, the body uses `x` then redefines it,

View file

@ -479,11 +479,9 @@ mod tests {
let n1 = NodeIndex::new(1); let n1 = NodeIndex::new(1);
let n2 = NodeIndex::new(2); let n2 = NodeIndex::new(2);
// Push n0
assert!(in_wl.insert(n0)); assert!(in_wl.insert(n0));
wl.push_back(n0); wl.push_back(n0);
// Push n1
assert!(in_wl.insert(n1)); assert!(in_wl.insert(n1));
wl.push_back(n1); wl.push_back(n1);
@ -492,7 +490,6 @@ mod tests {
// wl still has only 2 entries // wl still has only 2 entries
assert_eq!(wl.len(), 2); assert_eq!(wl.len(), 2);
// Pop n0
let popped = wl.pop_front().unwrap(); let popped = wl.pop_front().unwrap();
in_wl.remove(&popped); in_wl.remove(&popped);
assert_eq!(popped, n0); assert_eq!(popped, n0);
@ -503,7 +500,6 @@ mod tests {
assert!(in_wl.insert(n0)); assert!(in_wl.insert(n0));
wl.push_back(n0); wl.push_back(n0);
// Push n2
assert!(in_wl.insert(n2)); assert!(in_wl.insert(n2));
wl.push_back(n2); wl.push_back(n2);

View file

@ -1558,9 +1558,7 @@ mod tests {
)); ));
} }
// ─────────────────────────────────────────────────────────────────
// chain-receiver decomposition + chain_proxies tracking // chain-receiver decomposition + chain_proxies tracking
// ─────────────────────────────────────────────────────────────────
// //
// These tests pin the contract that: // These tests pin the contract that:
// 1. `try_chain_decompose` parses dotted callees into receiver + // 1. `try_chain_decompose` parses dotted callees into receiver +
@ -1981,12 +1979,10 @@ mod tests {
assert!(lc.contains(ResourceLifecycle::CLOSED)); assert!(lc.contains(ResourceLifecycle::CLOSED));
} }
// ─────────────────────────────────────────────────────────────────
// Pointer-analysis: PtrProxyHint::FieldOnly routes // Pointer-analysis: PtrProxyHint::FieldOnly routes
// single-dot proxy-acquire to chain_proxies, suppressing the // single-dot proxy-acquire to chain_proxies, suppressing the
// SymbolId path that would otherwise mark the field-aliased local // SymbolId path that would otherwise mark the field-aliased local
// as a leakable resource. // as a leakable resource.
// ─────────────────────────────────────────────────────────────────
#[test] #[test]
fn field_only_hint_routes_single_dot_acquire_to_chain_proxies() { fn field_only_hint_routes_single_dot_acquire_to_chain_proxies() {

View file

@ -9,9 +9,7 @@
use std::collections::HashMap; use std::collections::HashMap;
// ─────────────────────────────────────────────────────────────────────────────
// Public types // Public types
// ─────────────────────────────────────────────────────────────────────────────
/// Whether the directive suppresses on its own line or the next line. /// Whether the directive suppresses on its own line or the next line.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@ -30,9 +28,7 @@ pub struct SuppressionMeta {
pub directive_line: usize, pub directive_line: usize,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Internal types // Internal types
// ─────────────────────────────────────────────────────────────────────────────
/// A single rule matcher, either exact or wildcard-suffix (`foo.*`). /// A single rule matcher, either exact or wildcard-suffix (`foo.*`).
#[derive(Debug)] #[derive(Debug)]
@ -99,9 +95,7 @@ impl SuppressionIndex {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Canonical rule ID // Canonical rule ID
// ─────────────────────────────────────────────────────────────────────────────
/// Strip parenthetical suffix from a rule ID: /// Strip parenthetical suffix from a rule ID:
/// `"taint-unsanitised-flow (source 5:1)"` → `"taint-unsanitised-flow"`. /// `"taint-unsanitised-flow (source 5:1)"` → `"taint-unsanitised-flow"`.
@ -114,9 +108,7 @@ pub fn canonical_rule_id(id: &str) -> &str {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Comment style per language // Comment style per language
// ─────────────────────────────────────────────────────────────────────────────
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum CommentStyle { enum CommentStyle {
@ -152,9 +144,7 @@ fn comment_style_for_path(path: &std::path::Path) -> Option<CommentStyle> {
comment_style_for_ext(norm) comment_style_for_ext(norm)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Parser // Parser
// ─────────────────────────────────────────────────────────────────────────────
/// Parse inline suppression directives from `source`, using comment syntax /// Parse inline suppression directives from `source`, using comment syntax
/// appropriate for the given file path. /// appropriate for the given file path.
@ -479,9 +469,7 @@ fn parse_rule_ids(text: &str) -> Vec<RuleMatcher> {
.collect() .collect()
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -33,9 +33,7 @@ use super::state::{PathConstraint, SymbolicState};
use super::transfer::{self, SymexHeapCtx, SymexSummaryCtx}; use super::transfer::{self, SymexHeapCtx, SymexSummaryCtx};
use super::value::SymbolicValue; use super::value::SymbolicValue;
// ─────────────────────────────────────────────────────────────────────────────
// Budget constants // Budget constants
// ─────────────────────────────────────────────────────────────────────────────
/// Maximum branch forks per finding before falling back to single-path. /// Maximum branch forks per finding before falling back to single-path.
const MAX_FORKS_PER_FINDING: usize = 3; const MAX_FORKS_PER_FINDING: usize = 3;
@ -47,9 +45,7 @@ const MAX_PATHS_PER_FINDING: usize = 8;
/// ALL paths for one finding. Global, not per-path. /// ALL paths for one finding. Global, not per-path.
const MAX_TOTAL_STEPS: usize = 500; const MAX_TOTAL_STEPS: usize = 500;
// ─────────────────────────────────────────────────────────────────────────────
// Types // Types
// ─────────────────────────────────────────────────────────────────────────────
/// A single exploration path in flight. /// A single exploration path in flight.
/// ///
@ -103,9 +99,7 @@ pub(super) struct ExplorationResult {
pub interproc_cutoffs: Vec<super::interproc::CutoffReason>, pub interproc_cutoffs: Vec<super::interproc::CutoffReason>,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Reachability // Reachability
// ─────────────────────────────────────────────────────────────────────────────
/// Compute the set of blocks on some CFG path from source to sink. /// Compute the set of blocks on some CFG path from source to sink.
/// ///
@ -172,9 +166,7 @@ fn compute_source_sink_reachable(
forward.intersection(&backward).copied().collect() forward.intersection(&backward).copied().collect()
} }
// ─────────────────────────────────────────────────────────────────────────────
// Exploration engine // Exploration engine
// ─────────────────────────────────────────────────────────────────────────────
/// Run multi-path symbolic exploration for a single finding. /// Run multi-path symbolic exploration for a single finding.
/// ///
@ -1138,9 +1130,7 @@ fn try_extract_witness(
.or_else(|| state.sym_state.get_sink_witness(finding, ssa)) .or_else(|| state.sym_state.get_sink_witness(finding, ssa))
} }
// ─────────────────────────────────────────────────────────────────────────────
// Verdict aggregation // Verdict aggregation
// ─────────────────────────────────────────────────────────────────────────────
impl ExplorationResult { impl ExplorationResult {
/// Aggregate per-path outcomes into a single [`SymbolicVerdict`]. /// Aggregate per-path outcomes into a single [`SymbolicVerdict`].
@ -1221,9 +1211,7 @@ impl ExplorationResult {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Witness enrichment // Witness enrichment
// ─────────────────────────────────────────────────────────────────────────────
/// Append interprocedural context to a witness string. /// Append interprocedural context to a witness string.
/// ///
@ -1269,9 +1257,7 @@ fn append_interproc_context(
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -35,9 +35,7 @@ const MAX_FIELDS_PER_OBJECT: usize = 8;
/// `Elements` (taint unioned, value set to `Unknown`). /// `Elements` (taint unioned, value set to `Unknown`).
pub const MAX_TRACKED_INDICES: usize = 16; pub const MAX_TRACKED_INDICES: usize = 16;
// ─────────────────────────────────────────────────────────────────────────────
// Types // Types
// ─────────────────────────────────────────────────────────────────────────────
/// Heap key: allocation-site identity + field slot. /// Heap key: allocation-site identity + field slot.
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
@ -365,9 +363,7 @@ impl SymbolicHeap {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Helpers // Helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Resolve a container operation index argument to a [`FieldSlot`]. /// Resolve a container operation index argument to a [`FieldSlot`].
/// ///
@ -440,9 +436,7 @@ pub fn resolve_singleton_object(
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -45,9 +45,7 @@ use super::state::{PathConstraint, SymbolicState};
use super::transfer::{self, SymexHeapCtx, SymexSummaryCtx}; use super::transfer::{self, SymexHeapCtx, SymexSummaryCtx};
use super::value::{SymbolicValue, mk_phi}; use super::value::{SymbolicValue, mk_phi};
// ─────────────────────────────────────────────────────────────────────────────
// Constants // Constants
// ─────────────────────────────────────────────────────────────────────────────
/// Default max call depth (caller → callee → callee's callee → ...). /// Default max call depth (caller → callee → callee's callee → ...).
pub(crate) const DEFAULT_MAX_DEPTH: usize = 3; pub(crate) const DEFAULT_MAX_DEPTH: usize = 3;
@ -91,9 +89,7 @@ pub(crate) const DEFAULT_MAX_SCC_REENTRY: usize = 3;
/// Max cache entries before eviction (simple clear). /// Max cache entries before eviction (simple clear).
const MAX_CACHE_ENTRIES: usize = 64; const MAX_CACHE_ENTRIES: usize = 64;
// ─────────────────────────────────────────────────────────────────────────────
// Feature gate // Feature gate
// ─────────────────────────────────────────────────────────────────────────────
/// Check if interprocedural symbolic execution is enabled. /// Check if interprocedural symbolic execution is enabled.
/// ///
@ -106,9 +102,7 @@ pub fn interproc_enabled() -> bool {
.interprocedural .interprocedural
} }
// ─────────────────────────────────────────────────────────────────────────────
// Cutoff reasons // Cutoff reasons
// ─────────────────────────────────────────────────────────────────────────────
/// Structured record of why interprocedural execution was cut short. /// Structured record of why interprocedural execution was cut short.
/// ///
@ -234,9 +228,7 @@ impl fmt::Display for CutoffReason {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Context // Context
// ─────────────────────────────────────────────────────────────────────────────
/// Shared context for interprocedural symbolic execution. /// Shared context for interprocedural symbolic execution.
/// ///
@ -354,9 +346,7 @@ pub struct InterprocStats {
pub forks: usize, pub forks: usize,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Result types // Result types
// ─────────────────────────────────────────────────────────────────────────────
/// Result of executing a callee to completion. /// Result of executing a callee to completion.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -441,9 +431,7 @@ pub struct InterprocEvents {
pub cutoff_reasons: Vec<CutoffReason>, pub cutoff_reasons: Vec<CutoffReason>,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Merge policy // Merge policy
// ─────────────────────────────────────────────────────────────────────────────
/// Policy for merging multiple callee exit states into a single caller state. /// Policy for merging multiple callee exit states into a single caller state.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -467,9 +455,7 @@ pub fn select_merge_policy(exit_count: usize, has_cutoffs: bool) -> MergePolicy
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Cache // Cache
// ─────────────────────────────────────────────────────────────────────────────
/// Cache key abstraction of argument symbolic values. /// Cache key abstraction of argument symbolic values.
/// ///
@ -520,9 +506,7 @@ impl ArgAbstraction {
/// Cache type: maps (callee_name, arg_abstraction, heap_fingerprint) → CallOutcome. /// Cache type: maps (callee_name, arg_abstraction, heap_fingerprint) → CallOutcome.
pub type InterprocCache = HashMap<(String, ArgAbstraction, u64), CallOutcome>; pub type InterprocCache = HashMap<(String, ArgAbstraction, u64), CallOutcome>;
// ─────────────────────────────────────────────────────────────────────────────
// RAII re-entry guard // RAII re-entry guard
// ─────────────────────────────────────────────────────────────────────────────
/// RAII guard that increments a function's re-entry count on creation and /// RAII guard that increments a function's re-entry count on creation and
/// decrements it on drop. Ensures the count is correct on all exit paths. /// decrements it on drop. Ensures the count is correct on all exit paths.
@ -550,9 +534,7 @@ impl<'a> Drop for ReentryGuard<'a> {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Core execution // Core execution
// ─────────────────────────────────────────────────────────────────────────────
/// Execute a callee's SSA body interprocedurally. /// Execute a callee's SSA body interprocedurally.
/// ///
@ -1151,9 +1133,7 @@ fn handle_nested_calls(
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Exit state merging // Exit state merging
// ─────────────────────────────────────────────────────────────────────────────
/// Merge multiple callee exit states into a single state for the caller. /// Merge multiple callee exit states into a single state for the caller.
/// ///
@ -1256,9 +1236,7 @@ fn merge_most_tainted(states: &[CalleeExitState]) -> CalleeExitState {
}) })
} }
// ─────────────────────────────────────────────────────────────────────────────
// Heap delta // Heap delta
// ─────────────────────────────────────────────────────────────────────────────
/// Compute the set of heap fields that changed between initial and final state. /// Compute the set of heap fields that changed between initial and final state.
fn compute_heap_delta(initial: &SymbolicHeap, final_heap: &SymbolicHeap) -> Vec<HeapMutation> { fn compute_heap_delta(initial: &SymbolicHeap, final_heap: &SymbolicHeap) -> Vec<HeapMutation> {
@ -1293,9 +1271,7 @@ fn sym_value_structurally_eq(a: &SymbolicValue, b: &SymbolicValue) -> bool {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -34,9 +34,7 @@ pub struct LoopInfo {
doms: Dominators<NodeIndex>, doms: Dominators<NodeIndex>,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Public API // Public API
// ─────────────────────────────────────────────────────────────────────────────
/// Analyse loop structure in an SSA body. /// Analyse loop structure in an SSA body.
/// ///
@ -108,9 +106,7 @@ impl LoopInfo {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Internal helpers // Internal helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Build a petgraph from SSA block successors. /// Build a petgraph from SSA block successors.
/// ///
@ -304,9 +300,7 @@ fn is_simple_increment(ssa: &SsaBody, inc_val: SsaValue, phi_val: SsaValue) -> b
false false
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -46,9 +46,7 @@ use crate::ssa::type_facts::TypeKind;
use super::state::{PathConstraint, SymbolicState}; use super::state::{PathConstraint, SymbolicState};
// ─────────────────────────────────────────────────────────────────────────────
// Constants // Constants
// ─────────────────────────────────────────────────────────────────────────────
/// Maximum SMT queries per finding (across all paths). /// Maximum SMT queries per finding (across all paths).
const MAX_SMT_QUERIES_PER_FINDING: u32 = 10; const MAX_SMT_QUERIES_PER_FINDING: u32 = 10;
@ -60,9 +58,7 @@ const SMT_QUERY_TIMEOUT_MS: u32 = 500;
/// String theory (especially lexicographic ordering) is more expensive. /// String theory (especially lexicographic ordering) is more expensive.
const SMT_STRING_QUERY_TIMEOUT_MS: u32 = 500; const SMT_STRING_QUERY_TIMEOUT_MS: u32 = 500;
// ─────────────────────────────────────────────────────────────────────────────
// Types // Types
// ─────────────────────────────────────────────────────────────────────────────
/// Result of an SMT satisfiability check. /// Result of an SMT satisfiability check.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -126,9 +122,7 @@ fn warm_z3() {
}); });
} }
// ─────────────────────────────────────────────────────────────────────────────
// SmtContext // SmtContext
// ─────────────────────────────────────────────────────────────────────────────
impl SmtContext { impl SmtContext {
/// Create a new SMT context for one finding's exploration. /// Create a new SMT context for one finding's exploration.
@ -208,9 +202,7 @@ impl SmtContext {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Sort inference // Sort inference
// ─────────────────────────────────────────────────────────────────────────────
/// Try to determine that an SSA value is an integer from PathEnv facts. /// Try to determine that an SSA value is an integer from PathEnv facts.
fn is_known_int(v: SsaValue, env: &PathEnv) -> bool { fn is_known_int(v: SsaValue, env: &PathEnv) -> bool {
@ -303,9 +295,7 @@ fn force_str_var(var_map: &mut VarMap, v: SsaValue) -> Option<Z3Str> {
Some(z3_var) Some(z3_var)
} }
// ─────────────────────────────────────────────────────────────────────────────
// PathEnv seeding // PathEnv seeding
// ─────────────────────────────────────────────────────────────────────────────
/// Seed Z3 solver with known facts from PathEnv. /// Seed Z3 solver with known facts from PathEnv.
/// ///
@ -411,9 +401,7 @@ fn seed_from_path_env(solver: &Solver, var_map: &mut VarMap, env: &PathEnv) {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Constraint translation // Constraint translation
// ─────────────────────────────────────────────────────────────────────────────
/// Translate a single path constraint into a Z3 assertion. /// Translate a single path constraint into a Z3 assertion.
/// ///
@ -583,9 +571,7 @@ fn build_comparison_str(lhs: &Z3Str, op: CompOp, rhs: &Z3Str) -> z3::ast::Bool {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Escalation predicate // Escalation predicate
// ─────────────────────────────────────────────────────────────────────────────
/// Determine whether accumulated path constraints warrant SMT escalation. /// Determine whether accumulated path constraints warrant SMT escalation.
/// ///
@ -613,9 +599,7 @@ fn can_translate_operand(op: &Operand) -> bool {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -213,9 +213,7 @@ impl Default for SymbolicState {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -13,9 +13,7 @@ use crate::symbol::Lang;
use super::value::SymbolicValue; use super::value::SymbolicValue;
// ─────────────────────────────────────────────────────────────────────────────
// Types // Types
// ─────────────────────────────────────────────────────────────────────────────
/// Recognized string operation semantic. /// Recognized string operation semantic.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -56,9 +54,7 @@ pub struct SanitizerInfo {
pub is_global: bool, pub is_global: bool,
} }
// ─────────────────────────────────────────────────────────────────────────────
// Encoding/decoding transform types // Encoding/decoding transform types
// ─────────────────────────────────────────────────────────────────────────────
/// Category of encoding/decoding transform for symbolic modeling. /// Category of encoding/decoding transform for symbolic modeling.
/// ///
@ -141,9 +137,7 @@ pub struct TransformMethodInfo {
pub operand_source: StringOperandSource, pub operand_source: StringOperandSource,
} }
// ─────────────────────────────────────────────────────────────────────────────
// String method classification // String method classification
// ─────────────────────────────────────────────────────────────────────────────
/// Classify a callee as a recognized string method. /// Classify a callee as a recognized string method.
/// ///
@ -481,9 +475,7 @@ fn classify_c(method: &str) -> Option<StringMethodInfo> {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Encoding/decoding transform classification // Encoding/decoding transform classification
// ─────────────────────────────────────────────────────────────────────────────
/// Classify a callee as a recognized encoding/decoding transform. /// Classify a callee as a recognized encoding/decoding transform.
/// ///
@ -757,9 +749,7 @@ fn classify_transform_ruby(callee: &str) -> Option<TransformMethodInfo> {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Concrete encoding/decoding for witness rendering // Concrete encoding/decoding for witness rendering
// ─────────────────────────────────────────────────────────────────────────────
/// Apply encoding for witness rendering. /// Apply encoding for witness rendering.
/// ///
@ -939,9 +929,7 @@ fn hex_val(b: u8) -> Option<u8> {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Arg extraction helpers // Arg extraction helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Extract concrete pattern and replacement strings from args at given offset. /// Extract concrete pattern and replacement strings from args at given offset.
/// ///
@ -960,9 +948,7 @@ fn has_concrete_index(args: &[SymbolicValue], offset: usize) -> bool {
.unwrap_or(false) .unwrap_or(false)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Concrete evaluation // Concrete evaluation
// ─────────────────────────────────────────────────────────────────────────────
/// Evaluate a string operation on a concrete receiver string. /// Evaluate a string operation on a concrete receiver string.
/// ///
@ -986,9 +972,7 @@ pub fn evaluate_string_op_concrete(method: &StringMethod, receiver: &str) -> Opt
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Sanitizer detection // Sanitizer detection
// ─────────────────────────────────────────────────────────────────────────────
/// Detect whether a Replace operation acts as a security sanitizer. /// Detect whether a Replace operation acts as a security sanitizer.
/// ///
@ -1129,9 +1113,7 @@ fn is_global_replace(callee: &str, lang: Lang) -> bool {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -422,9 +422,7 @@ pub fn transfer_inst(
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Heap helpers // Heap helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Record a field store in the symbolic heap when the instruction defines /// Record a field store in the symbolic heap when the instruction defines
/// a dotted path (e.g., `user.name`). /// a dotted path (e.g., `user.name`).
@ -685,9 +683,7 @@ pub fn transfer_block(
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// String method dispatch // String method dispatch
// ─────────────────────────────────────────────────────────────────────────────
/// Attempt to model a callee as a recognized string operation. /// Attempt to model a callee as a recognized string operation.
/// ///
@ -809,9 +805,7 @@ fn try_transform_method(
Some(SymbolicCallResult { value, tainted }) Some(SymbolicCallResult { value, tainted })
} }
// ─────────────────────────────────────────────────────────────────────────────
// Cross-file symbolic summary resolution // Cross-file symbolic summary resolution
// ─────────────────────────────────────────────────────────────────────────────
/// Model a callee's return value from its SSA summary. /// Model a callee's return value from its SSA summary.
/// ///
@ -969,9 +963,7 @@ fn resolve_callee_symbolically(
model_from_summary(summary, arg_syms, all_operands, state, result_value) model_from_summary(summary, arg_syms, all_operands, state, result_value)
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -189,9 +189,7 @@ impl SymbolicValue {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Smart constructors, all tree-building goes through these // Smart constructors, all tree-building goes through these
// ─────────────────────────────────────────────────────────────────────────────
/// Build a binary arithmetic expression with concrete folding and depth bounding. /// Build a binary arithmetic expression with concrete folding and depth bounding.
/// ///
@ -316,9 +314,7 @@ pub fn mk_phi(operands: Vec<(BlockId, SymbolicValue)>) -> SymbolicValue {
SymbolicValue::Phi(operands) SymbolicValue::Phi(operands)
} }
// ─────────────────────────────────────────────────────────────────────────────
// String operation smart constructors // String operation smart constructors
// ─────────────────────────────────────────────────────────────────────────────
/// Build a `Trim` expression with concrete folding and depth bounding. /// Build a `Trim` expression with concrete folding and depth bounding.
pub fn mk_trim(s: SymbolicValue) -> SymbolicValue { pub fn mk_trim(s: SymbolicValue) -> SymbolicValue {
@ -458,9 +454,7 @@ pub fn mk_decode(kind: super::strings::TransformKind, s: SymbolicValue) -> Symbo
SymbolicValue::Decode(kind, Box::new(s)) SymbolicValue::Decode(kind, Box::new(s))
} }
// ─────────────────────────────────────────────────────────────────────────────
// Display, human-readable witness strings // Display, human-readable witness strings
// ─────────────────────────────────────────────────────────────────────────────
/// Maximum length for the Display output before truncation. /// Maximum length for the Display output before truncation.
const MAX_DISPLAY_LEN: usize = 256; const MAX_DISPLAY_LEN: usize = 256;
@ -538,9 +532,7 @@ fn display_inner(val: &SymbolicValue) -> String {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -17,9 +17,7 @@ use crate::taint::Finding;
use super::state::SymbolicState; use super::state::SymbolicState;
use super::value::SymbolicValue; use super::value::SymbolicValue;
// ─────────────────────────────────────────────────────────────────────────────
// Public API // Public API
// ─────────────────────────────────────────────────────────────────────────────
/// Extract a human-readable witness string for a confirmed finding. /// Extract a human-readable witness string for a confirmed finding.
/// ///
@ -118,9 +116,7 @@ pub fn extract_witness(
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Helpers // Helpers
// ─────────────────────────────────────────────────────────────────────────────
/// When the sink expression is a `Call`, find the most informative tainted /// When the sink expression is a `Call`, find the most informative tainted
/// argument to use for witness generation instead of the opaque return value. /// argument to use for witness generation instead of the opaque return value.
@ -464,9 +460,7 @@ fn evaluate_concrete(expr: &SymbolicValue) -> String {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Transformsink mismatch detection // Transformsink mismatch detection
// ─────────────────────────────────────────────────────────────────────────────
/// Heuristic check: does a protective transform in the expression match /// Heuristic check: does a protective transform in the expression match
/// the sink's vulnerability class? /// the sink's vulnerability class?
@ -529,9 +523,7 @@ fn cap_description(cap: Cap) -> &'static str {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Tests // Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -556,9 +556,7 @@ fn cross_file_sanitizer_resolved_via_global_summaries() {
); );
} }
// ─────────────────────────────────────────────────────────────────────────────
// Shared test helpers // Shared test helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Parse Rust source bytes → FileCfg /// Parse Rust source bytes → FileCfg
fn parse_rust(src: &[u8]) -> FileCfg { fn parse_rust(src: &[u8]) -> FileCfg {
@ -777,9 +775,7 @@ fn cross_file_sink_cap_only_site_leaves_primary_location_none() {
); );
} }
// ─────────────────────────────────────────────────────────────────────────────
// Multi-file integration tests (real parsing, full pass-1 → pass-2 pipeline) // Multi-file integration tests (real parsing, full pass-1 → pass-2 pipeline)
// ─────────────────────────────────────────────────────────────────────────────
#[test] #[test]
fn multi_file_source_to_sink_detected() { fn multi_file_source_to_sink_detected() {
@ -1070,9 +1066,7 @@ fn multi_file_chain_source_sanitize_sink_across_files() {
); );
} }
// ─────────────────────────────────────────────────────────────────────────────
// Edge-case unit tests // Edge-case unit tests
// ─────────────────────────────────────────────────────────────────────────────
#[test] #[test]
fn sanitizer_strips_only_matching_bits() { fn sanitizer_strips_only_matching_bits() {
@ -1435,9 +1429,7 @@ fn multiple_cross_file_sources_one_sanitised() {
); );
} }
// ─────────────────────────────────────────────────────────────────────────────
// Multi-language helpers and tests // Multi-language helpers and tests
// ─────────────────────────────────────────────────────────────────────────────
/// Parse source bytes for any supported language → FileCfg /// Parse source bytes for any supported language → FileCfg
fn parse_lang(src: &[u8], slug: &str, ts_lang: tree_sitter::Language) -> FileCfg { fn parse_lang(src: &[u8], slug: &str, ts_lang: tree_sitter::Language) -> FileCfg {
@ -1956,9 +1948,7 @@ fn ruby_source_to_sink() {
); );
} }
// ─────────────────────────────────────────────────────────────────────────────
// Cross-language multi-file tests // Cross-language multi-file tests
// ─────────────────────────────────────────────────────────────────────────────
// //
// Cross-language resolution now requires explicit InteropEdge declarations. // Cross-language resolution now requires explicit InteropEdge declarations.
// Without an edge, functions from different languages are never resolved , // Without an edge, functions from different languages are never resolved ,
@ -6158,9 +6148,7 @@ fn link_alternative_paths_three_way_group() {
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// Typed call-graph devirtualisation (typed_call_receivers) // Typed call-graph devirtualisation (typed_call_receivers)
// ─────────────────────────────────────────────────────────────────────────────
/// when a method call's receiver was constructed from a known /// when a method call's receiver was constructed from a known
/// constructor (`File::open` → `FileHandle`), the SSA-extraction /// constructor (`File::open` → `FileHandle`), the SSA-extraction

View file

@ -19,9 +19,7 @@ use std::{
thread, thread,
}; };
// ---------------------------------------------------------------------------
// Internal constants / helpers // Internal constants / helpers
// ---------------------------------------------------------------------------
type Paths = Vec<PathBuf>; type Paths = Vec<PathBuf>;
@ -84,7 +82,6 @@ fn build_overrides(root: &Path, cfg: &Config) -> ignore::overrides::Override {
}) })
} }
// ---------------------------------------------------------------------------
/// Walk `root` and send *batches* of paths through the returned channel. /// Walk `root` and send *batches* of paths through the returned channel.
pub fn spawn_file_walker(root: &Path, cfg: &Config) -> (Receiver<Paths>, JoinHandle<()>) { pub fn spawn_file_walker(root: &Path, cfg: &Config) -> (Receiver<Paths>, JoinHandle<()>) {
let _span = tracing::info_span!("spawn_file_walker", root = %root.display()).entered(); let _span = tracing::info_span!("spawn_file_walker", root = %root.display()).entered();