@@ -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,32 @@ predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
5663 )
5764}
5865
66+ /**
67+ * Holds if an additional step from `src` to `sink` through a call can be inferred from the
68+ * combination of a value-preserving step providing an alias between an input and the output
69+ * and a taint step from `src` to one the aliased nodes. 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 valueSourcePost |
75+ src .argumentOf ( call , _) and
76+ valueSource .argumentOf ( call , _) and
77+ src != valueSource and
78+ valueSourcePost .getPreUpdateNode ( ) = valueSource and
79+ DataFlow:: localFlowStep ( valueSource , DataFlow:: exprNode ( call ) ) and
80+ (
81+ // in-x -value-> out-y and in-z -taint-> out-y ==> in-z -taint-> in-x
82+ localAdditionalBasicTaintStep ( src , DataFlow:: exprNode ( call ) ) and
83+ sink = valueSourcePost
84+ or
85+ // in-x -value-> out-y and in-z -taint-> in-x ==> in-z -taint-> out-y
86+ localAdditionalBasicTaintStep ( src , valueSourcePost ) and
87+ sink = DataFlow:: exprNode ( call )
88+ )
89+ )
90+ }
91+
5992/**
6093 * Holds if the additional step from `src` to `sink` should be included in all
6194 * global taint flow configurations.
0 commit comments