@@ -90,33 +90,59 @@ string captureQualifierFlow(TargetApi api) {
90
90
result = asValueModel ( api , qualifierString ( ) , "ReturnValue" )
91
91
}
92
92
93
+ private int accessPathLimit ( ) { result = 2 }
94
+
93
95
/**
94
96
* A FlowState representing a tainted read.
95
97
*/
96
98
private class TaintRead extends DataFlow:: FlowState {
97
- TaintRead ( ) { this = "TaintRead" }
99
+ private int step ;
100
+
101
+ TaintRead ( ) { this = "TaintRead(" + step + ")" and step in [ 0 .. accessPathLimit ( ) ] }
102
+
103
+ /**
104
+ * Gets the flow state step number.
105
+ */
106
+ int getStep ( ) { result = step }
98
107
}
99
108
100
109
/**
101
110
* A FlowState representing a tainted write.
102
111
*/
103
112
private class TaintStore extends DataFlow:: FlowState {
104
- TaintStore ( ) { this = "TaintStore" }
113
+ private int step ;
114
+
115
+ TaintStore ( ) { this = "TaintStore(" + step + ")" and step in [ 1 .. accessPathLimit ( ) ] }
116
+
117
+ /**
118
+ * Gets the flow state step number.
119
+ */
120
+ int getStep ( ) { result = step }
105
121
}
106
122
107
123
/**
108
124
* A TaintTracking Configuration used for tracking flow through APIs.
109
125
* The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters.
110
126
*
111
127
* This can be used to generate Flow summaries for APIs from parameter to return.
128
+ *
129
+ * * We track at most two reads and at most two stores, meaning flow paths of the form
130
+ *
131
+ * ```
132
+ * parameter --value -->* node --read -->?
133
+ * node --taint -->* node --read -->?
134
+ * node --taint -->* node --store -->?
135
+ * node --taint -->* node --store -->?
136
+ * node --taint-->* return
137
+ * ```
112
138
*/
113
139
private class ThroughFlowConfig extends TaintTracking:: Configuration {
114
140
ThroughFlowConfig ( ) { this = "ThroughFlowConfig" }
115
141
116
142
override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowState state ) {
117
143
source instanceof DataFlow:: ParameterNode and
118
144
source .getEnclosingCallable ( ) instanceof TargetApi and
119
- state instanceof TaintRead
145
+ state . ( TaintRead ) . getStep ( ) = 0
120
146
}
121
147
122
148
override predicate isSink ( DataFlow:: Node sink , DataFlow:: FlowState state ) {
@@ -133,15 +159,17 @@ private class ThroughFlowConfig extends TaintTracking::Configuration {
133
159
exists ( DataFlowImplCommon:: TypedContent tc |
134
160
DataFlowImplCommon:: store ( node1 , tc , node2 , _) and
135
161
isRelevantContent ( tc .getContent ( ) ) and
136
- ( state1 instanceof TaintRead or state1 instanceof TaintStore ) and
137
- state2 instanceof TaintStore
162
+ (
163
+ state1 instanceof TaintRead and state2 .( TaintStore ) .getStep ( ) = 1
164
+ or
165
+ state1 .( TaintStore ) .getStep ( ) + 1 = state2 .( TaintStore ) .getStep ( )
166
+ )
138
167
)
139
168
or
140
169
exists ( DataFlow:: Content c |
141
170
DataFlowPrivate:: readStep ( node1 , c , node2 ) and
142
171
isRelevantContent ( c ) and
143
- state1 instanceof TaintRead and
144
- state2 instanceof TaintRead
172
+ state1 .( TaintRead ) .getStep ( ) + 1 = state2 .( TaintRead ) .getStep ( )
145
173
)
146
174
}
147
175
0 commit comments