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
// ─────────────────────────────────────────────────────────────────────────────
/// Level 1: parsed tree + lang info. No CFG construction.
struct ParsedSource<'a> {
@ -2161,9 +2159,7 @@ impl<'a> ParsedFile<'a> {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Pass 1: Extract function summaries (no taint analysis)
// ─────────────────────────────────────────────────────────────────────────────
/// Extract function summaries from pre-read bytes.
///
@ -2453,9 +2449,7 @@ pub fn extract_all_summaries_from_bytes(
))
}
// ─────────────────────────────────────────────────────────────────────────────
// Constant-argument suppression helper
// ─────────────────────────────────────────────────────────────────────────────
/// Returns `true` when the captured call node has only literal arguments
/// (string, number, boolean, null/nil/none), or identifier arguments that
@ -5355,9 +5349,7 @@ fn has_interpolation(node: tree_sitter::Node) -> bool {
false
}
// ─────────────────────────────────────────────────────────────────────────────
// 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")
/// 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)
// ─────────────────────────────────────────────────────────────────────────────
/// 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)
}
// ─────────────────────────────────────────────────────────────────────────────
// Fused single-pass: extract summaries + run full analysis in one parse/CFG
// ─────────────────────────────────────────────────────────────────────────────
/// Result of a fused analysis pass: both function summaries and diagnostics.
pub struct FusedResult {
@ -6090,9 +6078,7 @@ pub fn analyse_file_fused(
})
}
// ─────────────────────────────────────────────────────────────────────────────
// Text-based pattern scanning (non-tree-sitter files)
// ─────────────────────────────────────────────────────────────────────────────
/// Run text-based pattern scanners on files whose extension is not supported
/// by tree-sitter. Currently handles `.ejs` templates.

View file

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

View file

@ -20,9 +20,7 @@ use smallvec::SmallVec;
use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf};
// ─────────────────────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────────────────────
/// Metadata attached to each call-graph edge.
#[derive(Debug, Clone)]
@ -76,9 +74,7 @@ pub struct CallGraphAnalysis {
pub topo_scc_callee_first: Vec<usize>,
}
// ─────────────────────────────────────────────────────────────────────────────
// Callee-name normalization
// ─────────────────────────────────────────────────────────────────────────────
/// 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
// ─────────────────────────────────────────────────────────────────────────────
/// Per-language `(container, method_name)` → candidate [`FuncKey`] index.
///
@ -374,9 +368,7 @@ impl TypeHierarchyIndex {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Call-graph construction
// ─────────────────────────────────────────────────────────────────────────────
/// Build the whole-program call graph from merged summaries.
///
@ -742,9 +734,7 @@ fn resolve_via_interop(
None
}
// ─────────────────────────────────────────────────────────────────────────────
// SCC / topological analysis
// ─────────────────────────────────────────────────────────────────────────────
/// Compute SCC decomposition and topological ordering of the call graph.
///
@ -772,9 +762,7 @@ pub fn analyse(cg: &CallGraph) -> CallGraphAnalysis {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// File-level batch ordering
// ─────────────────────────────────────────────────────────────────────────────
/// A batch of files at a single topological position, annotated with whether
/// any contributing SCC contains mutual recursion (len > 1) and whether any
@ -1139,9 +1127,7 @@ pub(super) fn scc_file_batches<'a>(
(batches, orphans)
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
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
// -------------------------------------------------------------------------
/// Returns true if this CFG node can implicitly raise an exception (calls).
/// 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
// -------------------------------------------------------------------------
/// 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
@ -442,9 +438,7 @@ pub(super) fn build_begin_rescue<'a>(
}
}
// -------------------------------------------------------------------------
// switch handler, multi-way dispatch with fallthrough
// -------------------------------------------------------------------------
/// True for AST kinds that wrap a single switch case body.
pub(super) fn is_switch_case_kind(kind: &str) -> bool {
@ -780,9 +774,7 @@ pub(super) fn build_switch<'a>(
exits
}
// -------------------------------------------------------------------------
// try/catch/finally handler
// -------------------------------------------------------------------------
#[allow(clippy::too_many_arguments)]
pub(super) fn build_try<'a>(

View file

@ -388,9 +388,7 @@ fn js_catch_no_param_no_synthetic() {
);
}
// ─────────────────────────────────────────────────────────────────
// Ruby begin/rescue/ensure tests
// ─────────────────────────────────────────────────────────────────
#[test]
fn ruby_begin_rescue_has_exception_edges() {
@ -540,9 +538,7 @@ fn ruby_multiple_rescue_clauses() {
}
}
// ─────────────────────────────────────────────────────────────────
// Short-circuit evaluation tests
// ─────────────────────────────────────────────────────────────────
/// Helper: collect all If nodes from the CFG.
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");
}
// ─────────────────────────────────────────────────────────────────────
// Anonymous function body naming via syntactic context
// (derive_anon_fn_name_from_context coverage)
// ─────────────────────────────────────────────────────────────────────
fn js_body_names(src: &[u8]) -> Vec<String> {
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
// ─────────────────────────────────────────────────────────────────
/// JS `switch` should produce one synthetic dispatch `If` node per
/// 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
// with at least one Back edge that targets that header. Without these
// invariants the SSA loop-induction-variable phi placement is wrong
// and the abstract-interp widening points are missed.
// ─────────────────────────────────────────────────────────────────────
fn loop_headers(cfg: &Cfg) -> Vec<NodeIndex> {
cfg.node_indices()
@ -3998,9 +3988,7 @@ function outer(obj, x, y) {
assert_eq!(mline, 4, "obj.method(x) on line 4");
}
// ─────────────────────────────────────────────────────────────────
// Constant-branch fold: CondArith capture + evaluation
// ─────────────────────────────────────────────────────────────────
/// `CondArith::eval`/`eval_bool` must fold the two OWASP-Benchmark
/// arithmetic guard shapes to a definite boolean, using integer

View file

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

View file

@ -90,9 +90,7 @@ fn collect_ts_type_alias_local_collections(root: Node<'_>, code: &[u8], out: &mu
});
}
// ─────────────────────────────────────────────────────────────────────
// Java
// ─────────────────────────────────────────────────────────────────────
/// Walk the AST for `class_declaration` nodes whose body contains
/// `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
// ─────────────────────────────────────────────────────────────────────
/// Walk for `interface_declaration` and `class_declaration` nodes.
/// 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))
}
// ─────────────────────────────────────────────────────────────────────
// Rust
// ─────────────────────────────────────────────────────────────────────
/// Walk for `struct_item` nodes whose body lists named fields.
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)
// ─────────────────────────────────────────────────────────────────────
/// Walk for `class_definition` nodes whose superclass list contains
/// `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
}
// ─────────────────────────────────────────────────────────────────────
// Walk helper
// ─────────────────────────────────────────────────────────────────────
fn walk<'a, F: FnMut(Node<'a>)>(node: Node<'a>, f: &mut F) {
f(node);

View file

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

View file

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

View file

@ -135,9 +135,7 @@ fn map_fs_module_to_promises(module: &str) -> Option<String> {
}
}
// -------------------------------------------------------------------------
// Import binding extraction
// -------------------------------------------------------------------------
/// 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)
}
// -------------------------------------------------------------------------
// === PUBLIC ENTRY POINT =================================================
// -------------------------------------------------------------------------

View file

@ -955,9 +955,7 @@ pub struct LocalFuncSummary {
pub type Cfg = Graph<NodeInfo, EdgeKind>;
pub type FuncSummaries = HashMap<FuncKey, LocalFuncSummary>;
// -------------------------------------------------------------------------
// Per-body CFG types
// -------------------------------------------------------------------------
/// Opaque identifier for an executable body within a file.
#[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.
// Returns the set of *exit* nodes that need to be wired further.
// -------------------------------------------------------------------------
#[allow(clippy::too_many_arguments)]
pub(super) fn build_sub<'a>(
ast: Node<'a>,
@ -5099,9 +5095,7 @@ pub(super) fn build_sub<'a>(
current_body_id: BodyId,
) -> Vec<NodeIndex> {
match lookup(lang, ast.kind()) {
// ─────────────────────────────────────────────────────────────────
// IF/ELSE: two branches that remerge afterwards
// ─────────────────────────────────────────────────────────────────
Kind::If => {
// Some grammars (Go `if init; cond {}`, sibling C-style forms)
// 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.
// ─────────────────────────────────────────────────────────────────
Kind::While | Kind::For => {
let header = push_node(
g,
@ -5527,9 +5519,7 @@ pub(super) fn build_sub<'a>(
}
}
// ─────────────────────────────────────────────────────────────────
// Control-flow sinks (return / break / continue).
// ─────────────────────────────────────────────────────────────────
Kind::Return => {
if has_call_descendant(ast, lang) {
// 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,
),
// ─────────────────────────────────────────────────────────────────
// BLOCK: statements execute sequentially
// ─────────────────────────────────────────────────────────────────
Kind::SourceFile | Kind::Block => {
// Ruby body_statement with rescue/ensure = implicit begin/rescue
if lang == "ruby" && ast.kind() == "body_statement" {
@ -6655,9 +6643,7 @@ pub(super) fn build_sub<'a>(
analysis_rules,
),
// ─────────────────────────────────────────────────────────────────
// Every other node = simple sequential statement
// ─────────────────────────────────────────────────────────────────
_ => {
// React JSX `dangerouslySetInnerHTML={{__html: x}}` synthesis
// (Phase 06): handles arrow-bodied components like
@ -7145,21 +7131,5 @@ pub(crate) fn export_summaries(
.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)]
mod cfg_tests;

View file

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

View file

@ -207,9 +207,7 @@ fn collect_files(root: &Path, config: &Config) -> NyxResult<Vec<PathBuf>> {
Ok(out)
}
// ─────────────────────────────────────────────────────────────────────────────
// Text rendering
// ─────────────────────────────────────────────────────────────────────────────
/// Produce a human-readable tree. Files appear as top-level headers;
/// 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
// ─────────────────────────────────────────────────────────────────────────────
pub fn render_dot(map: &SurfaceMap) -> String {
let mut out = String::new();

View file

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

View file

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

View file

@ -191,9 +191,7 @@ pub fn detect_entries_in_file(
}
}
// ─────────────────────────────────────────────────────────────────────
// JS / TS — Next.js (Phase 10) + Express (Phase 16)
// ─────────────────────────────────────────────────────────────────────
fn detect_js_ts(root: Node<'_>, bytes: &[u8], path: &Path) -> HashMap<(usize, usize), EntryKind> {
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
// ─────────────────────────────────────────────────────────────────────
fn detect_python(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
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
}
// ─────────────────────────────────────────────────────────────────────
// Java — Spring + JAX-RS
// ─────────────────────────────────────────────────────────────────────
fn detect_java(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
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
}
// ─────────────────────────────────────────────────────────────────────
// Ruby — Rails + Sinatra
// ─────────────────────────────────────────────────────────────────────
fn detect_ruby(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
let mut entries: HashMap<(usize, usize), EntryKind> = HashMap::new();
@ -1108,9 +1100,7 @@ where
}
}
// ─────────────────────────────────────────────────────────────────────
// Rust — axum / actix-web / rocket
// ─────────────────────────────────────────────────────────────────────
fn detect_rust(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
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))
}
// ─────────────────────────────────────────────────────────────────────
// Go — net/http + gin / echo / chi
// ─────────────────────────────────────────────────────────────────────
fn detect_go(root: Node, bytes: &[u8]) -> HashMap<(usize, usize), EntryKind> {
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
}
// ─────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

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

View file

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

View file

@ -11,13 +11,8 @@ use std::time::Instant;
use tracing_subscriber::fmt::time;
use tracing_subscriber::prelude::*;
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) {
// let file_appender = RollingFileAppender::new(Rotation::HOURLY, "logs", "nyx-scanner.log");
// let (file_writer, guard) = non_blocking(file_appender);
let filter = if quiet {
EnvFilter::new("off")
} else {
@ -30,11 +25,6 @@ fn init_tracing(quiet: bool) {
.with_thread_ids(true)
.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();
}

View file

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

View file

@ -52,9 +52,7 @@ impl RustUseMap {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Module path derivation
// ─────────────────────────────────────────────────────────────────────────────
/// 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)
}
// ─────────────────────────────────────────────────────────────────────────────
// Use-declaration parsing
// ─────────────────────────────────────────────────────────────────────────────
/// Parse every top-level `use_declaration` of a Rust source tree into a
/// [`RustUseMap`].
@ -328,9 +324,7 @@ fn join_segments(prefix: &[String], suffix: &[String]) -> String {
all.join("::")
}
// ─────────────────────────────────────────────────────────────────────────────
// Resolution helpers
// ─────────────────────────────────────────────────────────────────────────────
/// 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
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -33,9 +33,7 @@ use super::state::{PathConstraint, SymbolicState};
use super::transfer::{self, SymexHeapCtx, SymexSummaryCtx};
use super::value::SymbolicValue;
// ─────────────────────────────────────────────────────────────────────────────
// Budget constants
// ─────────────────────────────────────────────────────────────────────────────
/// Maximum branch forks per finding before falling back to single-path.
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.
const MAX_TOTAL_STEPS: usize = 500;
// ─────────────────────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────────────────────
/// A single exploration path in flight.
///
@ -103,9 +99,7 @@ pub(super) struct ExplorationResult {
pub interproc_cutoffs: Vec<super::interproc::CutoffReason>,
}
// ─────────────────────────────────────────────────────────────────────────────
// Reachability
// ─────────────────────────────────────────────────────────────────────────────
/// 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()
}
// ─────────────────────────────────────────────────────────────────────────────
// Exploration engine
// ─────────────────────────────────────────────────────────────────────────────
/// 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))
}
// ─────────────────────────────────────────────────────────────────────────────
// Verdict aggregation
// ─────────────────────────────────────────────────────────────────────────────
impl ExplorationResult {
/// Aggregate per-path outcomes into a single [`SymbolicVerdict`].
@ -1221,9 +1211,7 @@ impl ExplorationResult {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Witness enrichment
// ─────────────────────────────────────────────────────────────────────────────
/// Append interprocedural context to a witness string.
///
@ -1269,9 +1257,7 @@ fn append_interproc_context(
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

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

View file

@ -45,9 +45,7 @@ use super::state::{PathConstraint, SymbolicState};
use super::transfer::{self, SymexHeapCtx, SymexSummaryCtx};
use super::value::{SymbolicValue, mk_phi};
// ─────────────────────────────────────────────────────────────────────────────
// Constants
// ─────────────────────────────────────────────────────────────────────────────
/// Default max call depth (caller → callee → callee's callee → ...).
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).
const MAX_CACHE_ENTRIES: usize = 64;
// ─────────────────────────────────────────────────────────────────────────────
// Feature gate
// ─────────────────────────────────────────────────────────────────────────────
/// Check if interprocedural symbolic execution is enabled.
///
@ -106,9 +102,7 @@ pub fn interproc_enabled() -> bool {
.interprocedural
}
// ─────────────────────────────────────────────────────────────────────────────
// Cutoff reasons
// ─────────────────────────────────────────────────────────────────────────────
/// Structured record of why interprocedural execution was cut short.
///
@ -234,9 +228,7 @@ impl fmt::Display for CutoffReason {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Context
// ─────────────────────────────────────────────────────────────────────────────
/// Shared context for interprocedural symbolic execution.
///
@ -354,9 +346,7 @@ pub struct InterprocStats {
pub forks: usize,
}
// ─────────────────────────────────────────────────────────────────────────────
// Result types
// ─────────────────────────────────────────────────────────────────────────────
/// Result of executing a callee to completion.
#[derive(Clone, Debug)]
@ -441,9 +431,7 @@ pub struct InterprocEvents {
pub cutoff_reasons: Vec<CutoffReason>,
}
// ─────────────────────────────────────────────────────────────────────────────
// Merge policy
// ─────────────────────────────────────────────────────────────────────────────
/// Policy for merging multiple callee exit states into a single caller state.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -467,9 +455,7 @@ pub fn select_merge_policy(exit_count: usize, has_cutoffs: bool) -> MergePolicy
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Cache
// ─────────────────────────────────────────────────────────────────────────────
/// Cache key abstraction of argument symbolic values.
///
@ -520,9 +506,7 @@ impl ArgAbstraction {
/// Cache type: maps (callee_name, arg_abstraction, heap_fingerprint) → CallOutcome.
pub type InterprocCache = HashMap<(String, ArgAbstraction, u64), CallOutcome>;
// ─────────────────────────────────────────────────────────────────────────────
// RAII re-entry guard
// ─────────────────────────────────────────────────────────────────────────────
/// 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.
@ -550,9 +534,7 @@ impl<'a> Drop for ReentryGuard<'a> {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Core execution
// ─────────────────────────────────────────────────────────────────────────────
/// Execute a callee's SSA body interprocedurally.
///
@ -1151,9 +1133,7 @@ fn handle_nested_calls(
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Exit state merging
// ─────────────────────────────────────────────────────────────────────────────
/// 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
// ─────────────────────────────────────────────────────────────────────────────
/// Compute the set of heap fields that changed between initial and final state.
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
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

@ -34,9 +34,7 @@ pub struct LoopInfo {
doms: Dominators<NodeIndex>,
}
// ─────────────────────────────────────────────────────────────────────────────
// Public API
// ─────────────────────────────────────────────────────────────────────────────
/// Analyse loop structure in an SSA body.
///
@ -108,9 +106,7 @@ impl LoopInfo {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Internal helpers
// ─────────────────────────────────────────────────────────────────────────────
/// 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
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

@ -46,9 +46,7 @@ use crate::ssa::type_facts::TypeKind;
use super::state::{PathConstraint, SymbolicState};
// ─────────────────────────────────────────────────────────────────────────────
// Constants
// ─────────────────────────────────────────────────────────────────────────────
/// Maximum SMT queries per finding (across all paths).
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.
const SMT_STRING_QUERY_TIMEOUT_MS: u32 = 500;
// ─────────────────────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────────────────────
/// Result of an SMT satisfiability check.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -126,9 +122,7 @@ fn warm_z3() {
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SmtContext
// ─────────────────────────────────────────────────────────────────────────────
impl SmtContext {
/// Create a new SMT context for one finding's exploration.
@ -208,9 +202,7 @@ impl SmtContext {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Sort inference
// ─────────────────────────────────────────────────────────────────────────────
/// Try to determine that an SSA value is an integer from PathEnv facts.
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)
}
// ─────────────────────────────────────────────────────────────────────────────
// PathEnv seeding
// ─────────────────────────────────────────────────────────────────────────────
/// 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
// ─────────────────────────────────────────────────────────────────────────────
/// 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
// ─────────────────────────────────────────────────────────────────────────────
/// Determine whether accumulated path constraints warrant SMT escalation.
///
@ -613,9 +599,7 @@ fn can_translate_operand(op: &Operand) -> bool {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

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

View file

@ -13,9 +13,7 @@ use crate::symbol::Lang;
use super::value::SymbolicValue;
// ─────────────────────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────────────────────
/// Recognized string operation semantic.
#[derive(Clone, Debug, PartialEq)]
@ -56,9 +54,7 @@ pub struct SanitizerInfo {
pub is_global: bool,
}
// ─────────────────────────────────────────────────────────────────────────────
// Encoding/decoding transform types
// ─────────────────────────────────────────────────────────────────────────────
/// Category of encoding/decoding transform for symbolic modeling.
///
@ -141,9 +137,7 @@ pub struct TransformMethodInfo {
pub operand_source: StringOperandSource,
}
// ─────────────────────────────────────────────────────────────────────────────
// String method classification
// ─────────────────────────────────────────────────────────────────────────────
/// Classify a callee as a recognized string method.
///
@ -481,9 +475,7 @@ fn classify_c(method: &str) -> Option<StringMethodInfo> {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Encoding/decoding transform classification
// ─────────────────────────────────────────────────────────────────────────────
/// 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
// ─────────────────────────────────────────────────────────────────────────────
/// Apply encoding for witness rendering.
///
@ -939,9 +929,7 @@ fn hex_val(b: u8) -> Option<u8> {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Arg extraction helpers
// ─────────────────────────────────────────────────────────────────────────────
/// 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)
}
// ─────────────────────────────────────────────────────────────────────────────
// Concrete evaluation
// ─────────────────────────────────────────────────────────────────────────────
/// 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
// ─────────────────────────────────────────────────────────────────────────────
/// Detect whether a Replace operation acts as a security sanitizer.
///
@ -1129,9 +1113,7 @@ fn is_global_replace(callee: &str, lang: Lang) -> bool {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

@ -422,9 +422,7 @@ pub fn transfer_inst(
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Heap helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Record a field store in the symbolic heap when the instruction defines
/// a dotted path (e.g., `user.name`).
@ -685,9 +683,7 @@ pub fn transfer_block(
}
}
// ─────────────────────────────────────────────────────────────────────────────
// String method dispatch
// ─────────────────────────────────────────────────────────────────────────────
/// Attempt to model a callee as a recognized string operation.
///
@ -809,9 +805,7 @@ fn try_transform_method(
Some(SymbolicCallResult { value, tainted })
}
// ─────────────────────────────────────────────────────────────────────────────
// Cross-file symbolic summary resolution
// ─────────────────────────────────────────────────────────────────────────────
/// 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)
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

@ -189,9 +189,7 @@ impl SymbolicValue {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Smart constructors, all tree-building goes through these
// ─────────────────────────────────────────────────────────────────────────────
/// 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)
}
// ─────────────────────────────────────────────────────────────────────────────
// String operation smart constructors
// ─────────────────────────────────────────────────────────────────────────────
/// Build a `Trim` expression with concrete folding and depth bounding.
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))
}
// ─────────────────────────────────────────────────────────────────────────────
// Display, human-readable witness strings
// ─────────────────────────────────────────────────────────────────────────────
/// Maximum length for the Display output before truncation.
const MAX_DISPLAY_LEN: usize = 256;
@ -538,9 +532,7 @@ fn display_inner(val: &SymbolicValue) -> String {
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {

View file

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

View file

@ -556,9 +556,7 @@ fn cross_file_sanitizer_resolved_via_global_summaries() {
);
}
// ─────────────────────────────────────────────────────────────────────────────
// Shared test helpers
// ─────────────────────────────────────────────────────────────────────────────
/// Parse Rust source bytes → 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)
// ─────────────────────────────────────────────────────────────────────────────
#[test]
fn multi_file_source_to_sink_detected() {
@ -1070,9 +1066,7 @@ fn multi_file_chain_source_sanitize_sink_across_files() {
);
}
// ─────────────────────────────────────────────────────────────────────────────
// Edge-case unit tests
// ─────────────────────────────────────────────────────────────────────────────
#[test]
fn sanitizer_strips_only_matching_bits() {
@ -1435,9 +1429,7 @@ fn multiple_cross_file_sources_one_sanitised() {
);
}
// ─────────────────────────────────────────────────────────────────────────────
// Multi-language helpers and tests
// ─────────────────────────────────────────────────────────────────────────────
/// Parse source bytes for any supported 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 resolution now requires explicit InteropEdge declarations.
// 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)
// ─────────────────────────────────────────────────────────────────────────────
/// when a method call's receiver was constructed from a known
/// constructor (`File::open` → `FileHandle`), the SSA-extraction

View file

@ -19,9 +19,7 @@ use std::{
thread,
};
// ---------------------------------------------------------------------------
// Internal constants / helpers
// ---------------------------------------------------------------------------
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.
pub fn spawn_file_walker(root: &Path, cfg: &Config) -> (Receiver<Paths>, JoinHandle<()>) {
let _span = tracing::info_span!("spawn_file_walker", root = %root.display()).entered();