Handoff: scope-aware reachability is the next taint-engine blocker (verified)
ober
521575c0da9431596c935428846336f9c90a11c6
--- a/HANDOFF_OPUS_4_8.md +++ b/HANDOFF_OPUS_4_8.md @@ -184,15 +184,29 @@ languages, so closing them is the tip of the larger work: - `java-field-decl-matches`: a `$T $L=$R` pattern matches a field_declaration, so field initializers propagate taint. - enhanced-for propagator: `for ($T $L : $R) {...}` taints the loop var. - Result: 8/18 java taint fixtures now flow structurally; removed the `tainting`, + - `java-parse-method-pattern` + `java-rewrite-param-metavars`: the parameter + -pattern preprocessor — gives bare `$X`/`...` params a synthetic type so + `public void $F(..., $X, ...)` parses; the matcher treats a synthetic + formal_parameter named `__sg_ellipsis__` as an ellipsis and `__sg_mvar_X` as + a metavar bound to the target param. Param-SOURCES now match like Semgrep. + Result: 8/18 java taint fixtures flow structurally; removed the `tainting`, `java-iterator-missed-propagation`, and `documentbuilderfactory` overfit clauses (java 42/42, smoke 321/321 each step). - STILL handler-side (the harder taint features, the `test` rule-id group can't be - retired until ALL its fixtures pass): type-aware assume-safe (numbers1/booleans1), - best-fit-sink ranges (sink11), getter/setter sensitivity, lambda propagators - (lambda1/propagator_lambda), jpa-sqli (propagator4), tainted-file-path, and FQN - resolution (final_globals2, metavariable-resolution-test: Foo -> org.foo.Foo). - The same engine retires the other languages' taint handlers + unblocks dart. + + **The next fundamental blocker is SCOPE-AWARE REACHABILITY (verified).** With + param-sources matching, `taint_assume_safe_numbers1` still fails because the + general engine's source→sink reachability is *positional/global*, not + per-method: every method's `$X` param reaches every `sink(...)`, so test1's + sink is (wrongly) flagged by test3-10's params. Confirmed empirically — a + numeric-typed-source filter (`source-state-numeric-typed-param?`, classifies + `int`/`long`/`Integer`… correctly) drops the right sources but findings persist + because cross-method non-numeric sources still reach. So the order is: (1) + per-method (CFG/scope) reachability, THEN (2) numeric/boolean source+value + type-classification, THEN (3) numeric-result value-analysis (`Integer.valueOf`, + `+`, `!=`). Each is real dataflow/type-inference work; together they're a + multi-day engine, and the `test` rule-id group needs ALL of them + best-fit-sink, + getter/setter, lambda, jpa, FQN before its overfit clause retires. The same + engine retires the other languages' taint handlers + unblocks dart. - a few per-language pattern hard-cases (go constant-folding/struct_tags, php metavar-call/non-prim-type, rust macro-call, kotlin named-ellipsis).