@@ -15,31 +15,82 @@ private class RatpackPromiseValueMethod extends Method, TaintPreservingCallable
1515 override predicate returnsTaintFrom ( int arg ) { arg = 0 }
1616}
1717
18- abstract private class SimpleFluentLambdaMethod extends Method {
19- SimpleFluentLambdaMethod ( ) { getNumberOfParameters ( ) = 1 }
20-
18+ abstract private class FluentLambdaMethod extends Method {
2119 /**
22- * Holds if this lambda consumes taint from the quaifier when `arg` is tainted.
20+ * Holds if this lambda consumes taint from the quaifier when `lambdaArg`
21+ * for `methodArg` is tainted.
2322 * Eg. `tainted.map(stillTainted -> ..)`
2423 */
25- abstract predicate consumesTaint ( int arg ) ;
24+ abstract predicate consumesTaint ( int methodArg , int lambdaArg ) ;
2625
2726 /**
28- * Holds if the lambda passed produces taint that taints the result of this method.
27+ * Holds if the lambda passed at the given `arg` position produces taint
28+ * that taints the result of this method.
2929 * Eg. `var tainted = CompletableFuture.supplyAsync(() -> taint());`
3030 */
31- predicate doesReturnTaint ( ) { none ( ) }
31+ predicate doesReturnTaint ( int arg ) { none ( ) }
32+ }
33+
34+ private class RatpackPromiseProviderethod extends Method , FluentLambdaMethod {
35+ RatpackPromiseProviderethod ( ) { isStatic ( ) and hasName ( [ "flatten" , "sync" ] ) }
36+
37+ override predicate consumesTaint ( int methodArg , int lambdaArg ) { none ( ) }
38+
39+ override predicate doesReturnTaint ( int arg ) { arg = 0 }
40+ }
41+
42+ abstract private class SimpleFluentLambdaMethod extends FluentLambdaMethod {
43+ override predicate consumesTaint ( int methodArg , int lambdaArg ) {
44+ methodArg = 0 and consumesTaint ( lambdaArg )
45+ }
46+
47+ /**
48+ * Holds if this lambda consumes taint from the quaifier when `arg` is tainted.
49+ * Eg. `tainted.map(stillTainted -> ..)`
50+ */
51+ abstract predicate consumesTaint ( int lambdaArg ) ;
3252}
3353
3454private class RatpackPromiseMapMethod extends SimpleFluentLambdaMethod {
3555 RatpackPromiseMapMethod ( ) {
3656 getDeclaringType ( ) instanceof RatpackPromise and
37- hasName ( [ "map" , "flatMap" ] )
57+ hasName ( [ "map" , "flatMap" , "blockingMap" ] )
3858 }
3959
40- override predicate consumesTaint ( int arg ) { arg = 0 }
60+ override predicate consumesTaint ( int lambdaArg ) { lambdaArg = 0 }
4161
42- override predicate doesReturnTaint ( ) { any ( ) }
62+ override predicate doesReturnTaint ( int arg ) { arg = 0 }
63+ }
64+
65+ /**
66+ * Represents the `mapIf` and `flatMapIf` method.
67+ *
68+ * `<O> Promise<O> mapIf(Predicate<T> predicate, Function<T, O> onTrue, Function<T, O> onFalse)`
69+ * `<O> Promise<O> flatMapIf(Predicate<T> predicate, Function<T, Promise<O>> onTrue, Function<T, Promise<O>> onFalse)`
70+ */
71+ private class RatpackPromiseMapIfMethod extends FluentLambdaMethod {
72+ RatpackPromiseMapIfMethod ( ) {
73+ getDeclaringType ( ) instanceof RatpackPromise and
74+ hasName ( [ "mapIf" , "flatMapIf" ] ) and
75+ getNumberOfParameters ( ) = 3
76+ }
77+
78+ override predicate consumesTaint ( int methodArg , int lambdaArg ) {
79+ methodArg = [ 1 , 2 , 3 ] and lambdaArg = 0
80+ }
81+
82+ override predicate doesReturnTaint ( int arg ) { arg = [ 1 , 2 ] }
83+ }
84+
85+ private class RatpackPromiseMapErrorMethod extends FluentLambdaMethod {
86+ RatpackPromiseMapErrorMethod ( ) {
87+ getDeclaringType ( ) instanceof RatpackPromise and
88+ hasName ( [ "mapError" , "flatMapError" ] )
89+ }
90+
91+ override predicate consumesTaint ( int methodArg , int lambdaArg ) { none ( ) }
92+
93+ override predicate doesReturnTaint ( int arg ) { arg = getNumberOfParameters ( ) - 1 }
4394}
4495
4596private class RatpackPromiseThenMethod extends SimpleFluentLambdaMethod {
@@ -48,16 +99,29 @@ private class RatpackPromiseThenMethod extends SimpleFluentLambdaMethod {
4899 hasName ( "then" )
49100 }
50101
51- override predicate consumesTaint ( int arg ) { arg = 0 }
102+ override predicate consumesTaint ( int lambdaArg ) { lambdaArg = 0 }
52103}
53104
54- private class RatpackPromiseNextMethod extends FluentMethod , SimpleFluentLambdaMethod {
55- RatpackPromiseNextMethod ( ) {
105+ private class RatpackPromiseFluentMethod extends FluentMethod , FluentLambdaMethod {
106+ RatpackPromiseFluentMethod ( ) {
56107 getDeclaringType ( ) instanceof RatpackPromise and
57- hasName ( "next" )
108+ not isStatic ( ) and
109+ exists ( ParameterizedType t |
110+ t instanceof RatpackPromise and
111+ t = getDeclaringType ( ) and
112+ t = getReturnType ( )
113+ )
58114 }
59115
60- override predicate consumesTaint ( int arg ) { arg = 0 }
116+ override predicate consumesTaint ( int methodArg , int lambdaArg ) {
117+ hasName ( [ "next" ] ) and methodArg = 0 and lambdaArg = 0
118+ or
119+ hasName ( [ "cacheIf" ] ) and methodArg = 0 and lambdaArg = 0
120+ or
121+ hasName ( [ "route" ] ) and methodArg = [ 0 , 1 ] and lambdaArg = 0
122+ }
123+
124+ override predicate doesReturnTaint ( int arg ) { hasName ( [ "flatMapIf" ] ) and arg = 1 }
61125}
62126
63127private class RatpackPromiseTaintPreservingStep extends AdditionalTaintStep {
@@ -70,10 +134,13 @@ private class RatpackPromiseTaintPreservingStep extends AdditionalTaintStep {
70134 * Holds if the method access qualifier `node1` has dataflow to the functional expression parameter `node2`.
71135 */
72136 predicate stepIntoLambda ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
73- exists ( MethodAccess ma , SimpleFluentLambdaMethod sflm , int arg | sflm .consumesTaint ( arg ) |
74- ma .getMethod ( ) = sflm and
137+ exists ( MethodAccess ma , FluentLambdaMethod flm , int methodArg , int lambdaArg |
138+ flm .consumesTaint ( methodArg , lambdaArg )
139+ |
140+ ma .getMethod ( ) = flm and
75141 node1 .asExpr ( ) = ma .getQualifier ( ) and
76- ma .getArgument ( 0 ) .( FunctionalExpr ) .asMethod ( ) .getParameter ( arg ) = node2 .asParameter ( )
142+ ma .getArgument ( methodArg ) .( FunctionalExpr ) .asMethod ( ) .getParameter ( lambdaArg ) =
143+ node2 .asParameter ( )
77144 )
78145 }
79146
@@ -82,13 +149,13 @@ private class RatpackPromiseTaintPreservingStep extends AdditionalTaintStep {
82149 * method access result `node2`.
83150 */
84151 predicate stepOutOfLambda ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
85- exists ( SimpleFluentLambdaMethod sflm , MethodAccess ma , FunctionalExpr fe |
86- sflm .doesReturnTaint ( )
152+ exists ( FluentLambdaMethod flm , MethodAccess ma , FunctionalExpr fe , int arg |
153+ flm .doesReturnTaint ( arg )
87154 |
88155 fe .asMethod ( ) .getBody ( ) .getAStmt ( ) .( ReturnStmt ) .getResult ( ) = node1 .asExpr ( ) and
89- ma .getMethod ( ) = sflm and
156+ ma .getMethod ( ) = flm and
90157 node2 .asExpr ( ) = ma and
91- ma .getArgument ( 0 ) = fe
158+ ma .getArgument ( arg ) = fe
92159 )
93160 }
94161}
0 commit comments