@@ -90,33 +90,59 @@ string captureQualifierFlow(TargetApi api) {
9090 result = asValueModel ( api , qualifierString ( ) , "ReturnValue" )
9191}
9292
93+ private int accessPathLimit ( ) { result = 2 }
94+
9395/**
9496 * A FlowState representing a tainted read.
9597 */
9698private 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 }
98107}
99108
100109/**
101110 * A FlowState representing a tainted write.
102111 */
103112private 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 }
105121}
106122
107123/**
108124 * A TaintTracking Configuration used for tracking flow through APIs.
109125 * The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters.
110126 *
111127 * 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+ * ```
112138 */
113139private class ThroughFlowConfig extends TaintTracking:: Configuration {
114140 ThroughFlowConfig ( ) { this = "ThroughFlowConfig" }
115141
116142 override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowState state ) {
117143 source instanceof DataFlow:: ParameterNode and
118144 source .getEnclosingCallable ( ) instanceof TargetApi and
119- state instanceof TaintRead
145+ state . ( TaintRead ) . getStep ( ) = 0
120146 }
121147
122148 override predicate isSink ( DataFlow:: Node sink , DataFlow:: FlowState state ) {
@@ -133,15 +159,17 @@ private class ThroughFlowConfig extends TaintTracking::Configuration {
133159 exists ( DataFlowImplCommon:: TypedContent tc |
134160 DataFlowImplCommon:: store ( node1 , tc , node2 , _) and
135161 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+ )
138167 )
139168 or
140169 exists ( DataFlow:: Content c |
141170 DataFlowPrivate:: readStep ( node1 , c , node2 ) and
142171 isRelevantContent ( c ) and
143- state1 instanceof TaintRead and
144- state2 instanceof TaintRead
172+ state1 .( TaintRead ) .getStep ( ) + 1 = state2 .( TaintRead ) .getStep ( )
145173 )
146174 }
147175
0 commit comments