mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-06 19:35:13 +02:00
* refactor: Update comments for clarity and add expectations.json files for performance metrics * feat: Implement FP guard for JS/TS local-collection receivers to suppress missing ownership checks * feat: Enhance Rust parameter handling to classify local collections and prevent false ownership checks * refactor: Simplify code formatting for better readability in multiple files * refactor: Improve UTF-8 sequence length handling and enhance clarity in loop iteration * feat: Update Java and Python patterns to include new security rules * refactor: Improve comment clarity and consistency across multiple Rust files * refactor: Simplify code formatting for improved readability in integration tests and module files * refactor: Improve comment formatting and enhance clarity in assertions across multiple files
98 lines
3.9 KiB
Rust
98 lines
3.9 KiB
Rust
//! Integration tests for parameter-granularity points-to summaries:
|
|
//! they carry alias information across file boundaries, closing
|
|
//! cross-file taint flows that travel through shared-object mutation
|
|
//! rather than through return values.
|
|
//!
|
|
//! Three fixtures cover distinct structural shapes of the summary
|
|
//! channel:
|
|
//!
|
|
//! * `cross_file_alias_mutating_helper` (Java), a void-returning
|
|
//! helper that stores its second argument into a field of its first
|
|
//! argument. Without the points-to channel the cross-file summary
|
|
//! loses every taint edge (void return, no container-op in
|
|
//! pointsto.rs). With it the helper emits a `Param(1) → Param(0)`
|
|
//! edge and the caller observes the field write through the argument
|
|
//! alias, producing a Runtime.exec finding.
|
|
//!
|
|
//! * `cross_file_alias_returned_alias` (JS), a passthrough helper
|
|
//! whose return aliases its first parameter. `param_to_return` with
|
|
//! `Identity` already covered the taint cap; the points-to channel
|
|
//! adds the heap-identity alias `Param(0) → Return` so the caller
|
|
//! threads the points-to set through the call. The existing
|
|
//! shell-exec sink must still fire, a regression guard on the
|
|
//! return-alias channel.
|
|
//!
|
|
//! * `cross_file_alias_bounded_graph` (Python), a helper with a 20-
|
|
//! edge alias graph that intentionally overflows `MAX_ALIAS_EDGES`.
|
|
//! The assertion is that the scan *terminates* under the bounded
|
|
//! analysis and falls back to the conservative
|
|
//! `PointsToSummary::overflow` behaviour, not a specific finding
|
|
//! count, overflow is an operational guarantee, not a precision one.
|
|
|
|
mod common;
|
|
|
|
use common::{scan_fixture_dir, validate_expectations};
|
|
use nyx_scanner::utils::config::AnalysisMode;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
fn fixture_path(name: &str) -> PathBuf {
|
|
Path::new(env!("CARGO_MANIFEST_DIR"))
|
|
.join("tests")
|
|
.join("fixtures")
|
|
.join(name)
|
|
}
|
|
|
|
#[test]
|
|
fn cross_file_alias_mutating_helper() {
|
|
let dir = fixture_path("cross_file_alias_mutating_helper");
|
|
let diags = scan_fixture_dir(&dir, AnalysisMode::Full);
|
|
validate_expectations(&diags, &dir);
|
|
}
|
|
|
|
#[test]
|
|
fn cross_file_alias_returned_alias() {
|
|
let dir = fixture_path("cross_file_alias_returned_alias");
|
|
let diags = scan_fixture_dir(&dir, AnalysisMode::Full);
|
|
validate_expectations(&diags, &dir);
|
|
}
|
|
|
|
#[test]
|
|
fn cross_file_alias_bounded_graph() {
|
|
let dir = fixture_path("cross_file_alias_bounded_graph");
|
|
let diags = scan_fixture_dir(&dir, AnalysisMode::Full);
|
|
validate_expectations(&diags, &dir);
|
|
}
|
|
|
|
/// Factory pattern: `makeBag()` returns a fresh `[]` and
|
|
/// `fillBag(bag, val)` stores into it. Exercises
|
|
/// `PointsToSummary.returns_fresh_alloc`, which synthesises a heap
|
|
/// identity for the factory's call result so subsequent container ops
|
|
/// in the caller have a heap cell to write into and read from.
|
|
#[test]
|
|
fn cross_file_container_factory() {
|
|
let dir = fixture_path("cross_file_container_factory");
|
|
let diags = scan_fixture_dir(&dir, AnalysisMode::Full);
|
|
validate_expectations(&diags, &dir);
|
|
}
|
|
|
|
/// Receiver-chain regression: tainted receiver flows through
|
|
/// `tainted.trim().toLowerCase()`, both zero-arg, and into
|
|
/// `Runtime.exec`. Pins the existing receiver-fallback behaviour so
|
|
/// heap-aliasing changes do not regress it.
|
|
#[test]
|
|
fn receiver_chain_taint_java() {
|
|
let dir = fixture_path("receiver_chain_taint_java");
|
|
let diags = scan_fixture_dir(&dir, AnalysisMode::Full);
|
|
validate_expectations(&diags, &dir);
|
|
}
|
|
|
|
/// Callback-alias regression: cross-file sink reached through
|
|
/// a two-hop local alias chain (`const f = helpers.dangerous; const g = f; g(x)`).
|
|
/// Pins whether the engine's name-keyed callback-binding resolution
|
|
/// walks the alias chain far enough to connect `g` → `dangerous`.
|
|
#[test]
|
|
fn cross_file_callback_alias() {
|
|
let dir = fixture_path("cross_file_callback_alias");
|
|
let diags = scan_fixture_dir(&dir, AnalysisMode::Full);
|
|
validate_expectations(&diags, &dir);
|
|
}
|