@@ -11,6 +11,7 @@ private import semmle.code.java.frameworks.spring.SpringController
1111private import semmle.code.java.frameworks.spring.SpringHttp
1212private import semmle.code.java.frameworks.Networking
1313private import semmle.code.java.dataflow.ExternalFlow
14+ private import semmle.code.java.dataflow.internal.DataFlowPrivate
1415import semmle.code.java.dataflow.FlowSteps
1516
1617/**
@@ -41,6 +42,12 @@ predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
4142 * different objects.
4243 */
4344predicate localAdditionalTaintStep ( DataFlow:: Node src , DataFlow:: Node sink ) {
45+ localAdditionalBasicTaintStep ( src , sink )
46+ or
47+ composedValueAndTaintModelStep ( src , sink )
48+ }
49+
50+ private predicate localAdditionalBasicTaintStep ( DataFlow:: Node src , DataFlow:: Node sink ) {
4451 localAdditionalTaintExprStep ( src .asExpr ( ) , sink .asExpr ( ) )
4552 or
4653 localAdditionalTaintUpdateStep ( src .asExpr ( ) ,
@@ -56,6 +63,31 @@ predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
5663 )
5764}
5865
66+ /**
67+ * Holds if an additional step from `src` to `sink` can be inferred from a value-preserving step
68+ * across a method callsite (from input to input, or input to result) and a taint-preserving step
69+ * across the same callsite from a different input. For example, if we know that `f(a, b)` returns
70+ * the exact value of `a` and also propagates taint from `b` to its result, then we also know that
71+ * `a` is tainted after `f` completes, and vice versa.
72+ */
73+ private predicate composedValueAndTaintModelStep ( ArgumentNode src , DataFlow:: Node sink ) {
74+ exists ( Call call , ArgumentNode valueSource , DataFlow:: PostUpdateNode valueSourcePun |
75+ src .argumentOf ( call , _) and
76+ valueSource .argumentOf ( call , _) and
77+ valueSourcePun .getPreUpdateNode ( ) = valueSource and
78+ DataFlow:: localFlowStep ( valueSource , DataFlow:: exprNode ( call ) ) and
79+ (
80+ // in-x -value-> out-y and in-z -taint-> out-y ==> in-z -taint-> in-x
81+ localAdditionalBasicTaintStep ( src , DataFlow:: exprNode ( call ) ) and
82+ sink = valueSourcePun
83+ or
84+ // in-x -value-> out-y and in-z -taint-> in-x ==> in-z -taint-> out-y
85+ localAdditionalBasicTaintStep ( src , valueSourcePun ) and
86+ sink = DataFlow:: exprNode ( call )
87+ )
88+ )
89+ }
90+
5991/**
6092 * Holds if the additional step from `src` to `sink` should be included in all
6193 * global taint flow configurations.
0 commit comments