Document argument-taint attempt + lesson (syntactic token-in-arg too broad)
ober
f4a743aa97ffc6d0c8defb21fdcce785ca0f8aa4
--- a/HANDOFF_OPUS_4_8.md +++ b/HANDOFF_OPUS_4_8.md @@ -220,10 +220,22 @@ languages, so closing them is the tip of the larger work: NOTE: did NOT touch `access-path-from-text` globally — that broke 3 smoke taint tests by making `direct-call-argument-text` dig into inner-call args. **(3b) STILL TODO base-flow:** argument-taint `sink(f(x))` (x is an ARG not a - receiver — test8/9/10 `Integer.valueOf(x)`), and binary-expr / cast RHS in + receiver — test8/9 `Integer.valueOf(x)`), and binary-expr / cast RHS in propagators (`w = v + x.getSomething()` test7, `t = (int)x.getSomething()` test5) which `field-source-taints-base-text?` won't anchor. THEN (3c) - value-analysis (`.length`→numeric test4, string-concat test7). + value-analysis (`.length`→numeric test4, `.compareTo`→numeric test10, + string-concat test7). + ATTEMPTED + REVERTED (2026-06-02): a syntactic `source-token-in-sink-arg?` + (bare-identifier source appears as a token in the sink's argument) handled + `sink(wrap(x))` but is TOO SYNTACTIC — it ignores labels/requires, sanitizers, + and by-side-effect ordering, so it broke 7 smoke taint tests (the metavar + branch matched a `source($X)` argument; a propagated label-source's NAME `foo` + matched unrelated sinks; by-side-effect typestate sources reached every call). + LESSON: argument-taint must flow through the propagation graph — the call's + RESULT becomes a derived taint-state that respects labels/sanitizers — not a + text token match. A real subproject, deferred. The RECEIVER fix (3a) is + safe precisely because it is anchored on the source variable as the + expression's base, which a derived/label/arg occurrence can't spoof. The `test` rule-id group needs (2)+(3a/b/c) + best-fit-sink, getter/setter, lambda, jpa, FQN before its overfit clause retires. The same engine retires the other languages' taint handlers + unblocks dart.