mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-09 19:45:13 +02:00
[pitboss/grind] deferred session-0019 (20260517T044708Z-e058)
This commit is contained in:
parent
f87ef7f118
commit
b5696c99e2
1 changed files with 181 additions and 1 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/// Dynamic verification benchmarks (§8.4).
|
||||
///
|
||||
/// Tracks six cost anchors:
|
||||
/// Tracks the per-scan cost anchors:
|
||||
///
|
||||
/// 1. `harness_build_cold` — fresh workdir, spec → BuiltHarness (source gen + disk write).
|
||||
/// 2. `harness_build_warm` — same spec, workdir already staged (file write skipped).
|
||||
|
|
@ -9,6 +9,25 @@
|
|||
/// 4. `docker_image_build` — cold image pull/build for the python:3-slim base.
|
||||
/// 5. `docker_exec_warm` — `docker exec` into a running container (no cold start).
|
||||
/// 6. `docker_payload_cost` — per-payload sandbox cost via docker backend end-to-end.
|
||||
/// 7. `composite_chain_reverify_dispatch` — `reverify_top_chains` on a
|
||||
/// synthetic 3-member chain with no member diags. Measures the no-derive
|
||||
/// dispatch path (chain_step_specs miss, early-exit build/run loops,
|
||||
/// Inconclusive verdict allocation, severity downgrade).
|
||||
/// 8. `composite_chain_reverify_stub_confirmed` — same chain shape, stubbed
|
||||
/// reverifier returning `Confirmed`. Measures the apply-verdict happy path
|
||||
/// (no severity bucket change).
|
||||
/// 9. `composite_chain_reverify_top_n_slice` — 5-chain slice with `top_n=3`.
|
||||
/// Measures the slice traversal cost so a regression that walks the full
|
||||
/// slice instead of the prefix is visible.
|
||||
///
|
||||
/// Wall-clock budget anchors for the composite reverify path (per the
|
||||
/// Phase 26 acceptance literal): the live process backend stays under
|
||||
/// 400ms per 3-member chain, the docker backend under 1500ms. Those
|
||||
/// live-run numbers are covered by the
|
||||
/// `flask_eval_chain_reverify_populates_dynamic_verdict` integration
|
||||
/// test in `tests/chain_emission_e2e.rs`; the microbenches here anchor
|
||||
/// the dispatch + verdict-application overhead so regressions on the
|
||||
/// API-shape half land in the criterion baseline.
|
||||
///
|
||||
/// Baselines committed to `benches/dynamic_bench_baseline.json`.
|
||||
/// Run: `cargo bench --features dynamic -- dynamic`
|
||||
|
|
@ -386,6 +405,164 @@ fn bench_php_harness_build_cold(c: &mut Criterion) {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn mk_chain_member(hash: u64, idx: usize) -> nyx_scanner::chain::FindingRef {
|
||||
use nyx_scanner::surface::SourceLocation;
|
||||
nyx_scanner::chain::FindingRef {
|
||||
finding_id: format!("bench-chain-member-{idx}"),
|
||||
stable_hash: hash,
|
||||
location: SourceLocation::new("bench/synthetic.py", (idx as u32) + 1, 1),
|
||||
rule_id: "taint-unsanitised-flow".into(),
|
||||
cap_bits: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn mk_synthetic_chain(hash: u64, members: usize) -> nyx_scanner::chain::ChainFinding {
|
||||
use nyx_scanner::chain::{ChainFinding, ChainSeverity, ChainSink, ImpactCategory};
|
||||
ChainFinding {
|
||||
stable_hash: hash,
|
||||
members: (0..members)
|
||||
.map(|i| mk_chain_member(hash.wrapping_add(i as u64 + 1), i))
|
||||
.collect(),
|
||||
sink: ChainSink {
|
||||
file: "bench/synthetic.py".into(),
|
||||
line: 99,
|
||||
col: 1,
|
||||
function_name: "sink".into(),
|
||||
cap_bits: 0,
|
||||
},
|
||||
implied_impact: ImpactCategory::Rce,
|
||||
severity: ChainSeverity::Critical,
|
||||
score: 100.0,
|
||||
dynamic_verdict: None,
|
||||
reverify_reason: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
struct BenchConfirmedReverifier;
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
impl nyx_scanner::chain::CompositeReverifier for BenchConfirmedReverifier {
|
||||
fn reverify(
|
||||
&self,
|
||||
_chain: &nyx_scanner::chain::ChainFinding,
|
||||
_member_diags: &[nyx_scanner::commands::scan::Diag],
|
||||
_surface: &nyx_scanner::surface::SurfaceMap,
|
||||
_opts: &nyx_scanner::dynamic::verify::VerifyOptions,
|
||||
) -> nyx_scanner::evidence::VerifyResult {
|
||||
nyx_scanner::evidence::VerifyResult {
|
||||
finding_id: "bench".into(),
|
||||
status: nyx_scanner::evidence::VerifyStatus::Confirmed,
|
||||
triggered_payload: None,
|
||||
reason: None,
|
||||
inconclusive_reason: None,
|
||||
detail: None,
|
||||
attempts: vec![],
|
||||
toolchain_match: None,
|
||||
differential: None,
|
||||
replay_stable: None,
|
||||
wrong: None,
|
||||
hardening_outcome: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Phase 26 dispatch-cost anchor: synthetic 3-member chain with no
|
||||
/// matching member diags. The reverifier walks chain_step_specs (3
|
||||
/// HashMap misses → 3 NoFlowSteps errors), the build loop sees zero
|
||||
/// derived specs and exits early, the run loop sees zero built steps
|
||||
/// and exits early. The composed VerifyResult is allocated and applied
|
||||
/// via `apply_dynamic_verdict` (Inconclusive → severity downgrade).
|
||||
///
|
||||
/// This is the no-toolchain-dep dispatch overhead — a regression here
|
||||
/// signals a hot-path allocation introduced into the reverify pipeline.
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn bench_composite_chain_reverify_dispatch(c: &mut Criterion) {
|
||||
use nyx_scanner::chain::reverify;
|
||||
use nyx_scanner::dynamic::verify::VerifyOptions;
|
||||
use nyx_scanner::surface::SurfaceMap;
|
||||
|
||||
let surface = SurfaceMap::new();
|
||||
let opts = VerifyOptions::default();
|
||||
|
||||
c.bench_function("composite_chain_reverify_dispatch", |b| {
|
||||
b.iter(|| {
|
||||
let mut chains = [mk_synthetic_chain(0xC1A1, 3)];
|
||||
let _ = reverify::reverify_top_chains(&mut chains, &[], &surface, &opts, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Phase 26 stub-reverifier happy-path anchor: synthetic 3-member
|
||||
/// chain driven through `reverify_top_chains_with` + a stubbed
|
||||
/// reverifier returning `Confirmed`. Measures the apply-verdict path
|
||||
/// when the verdict does NOT trigger a severity downgrade, so the
|
||||
/// `ChainReverifyResult` allocation + `chain.apply_dynamic_verdict`
|
||||
/// transition cost is exercised independent of the verdict-side
|
||||
/// allocation in the dispatch bench.
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn bench_composite_chain_reverify_stub_confirmed(c: &mut Criterion) {
|
||||
use nyx_scanner::chain::reverify;
|
||||
use nyx_scanner::dynamic::verify::VerifyOptions;
|
||||
use nyx_scanner::surface::SurfaceMap;
|
||||
|
||||
let surface = SurfaceMap::new();
|
||||
let opts = VerifyOptions::default();
|
||||
let reverifier = BenchConfirmedReverifier;
|
||||
|
||||
c.bench_function("composite_chain_reverify_stub_confirmed", |b| {
|
||||
b.iter(|| {
|
||||
let mut chains = [mk_synthetic_chain(0xC2A2, 3)];
|
||||
let _ = reverify::reverify_top_chains_with(
|
||||
&mut chains,
|
||||
&[],
|
||||
&surface,
|
||||
&opts,
|
||||
1,
|
||||
&reverifier,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Phase 26 top-N slice anchor: 5-chain slice with `top_n=3`. Asserts
|
||||
/// (by way of regression) that the reverify pass never walks past the
|
||||
/// top-N prefix. The fan-in is the per-chain dispatch cost times three;
|
||||
/// a regression that drops the `bound = top_n.min(chains.len())` cap
|
||||
/// would show up as a ~5/3 increase in this bench.
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn bench_composite_chain_reverify_top_n_slice(c: &mut Criterion) {
|
||||
use nyx_scanner::chain::reverify;
|
||||
use nyx_scanner::dynamic::verify::VerifyOptions;
|
||||
use nyx_scanner::surface::SurfaceMap;
|
||||
|
||||
let surface = SurfaceMap::new();
|
||||
let opts = VerifyOptions::default();
|
||||
let reverifier = BenchConfirmedReverifier;
|
||||
|
||||
c.bench_function("composite_chain_reverify_top_n_slice", |b| {
|
||||
b.iter(|| {
|
||||
let mut chains: [nyx_scanner::chain::ChainFinding; 5] = [
|
||||
mk_synthetic_chain(0xC301, 3),
|
||||
mk_synthetic_chain(0xC302, 3),
|
||||
mk_synthetic_chain(0xC303, 3),
|
||||
mk_synthetic_chain(0xC304, 3),
|
||||
mk_synthetic_chain(0xC305, 3),
|
||||
];
|
||||
let _ = reverify::reverify_top_chains_with(
|
||||
&mut chains,
|
||||
&[],
|
||||
&surface,
|
||||
&opts,
|
||||
3,
|
||||
&reverifier,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn bench_noop(_c: &mut Criterion) {}
|
||||
|
||||
|
|
@ -409,6 +586,9 @@ criterion_group!(
|
|||
bench_go_harness_build_cold,
|
||||
bench_java_harness_build_cold,
|
||||
bench_php_harness_build_cold,
|
||||
bench_composite_chain_reverify_dispatch,
|
||||
bench_composite_chain_reverify_stub_confirmed,
|
||||
bench_composite_chain_reverify_top_n_slice,
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue