@@ -18,17 +18,35 @@ private class ReturnNodeExt extends DataFlow::Node {
1818 kind = DataFlowImplCommon:: getParamReturnPosition ( this , _) .getKind ( )
1919 }
2020
21- string getOutput ( ) {
22- kind instanceof DataFlowImplCommon:: ValueReturnKind and
21+ /**
22+ * Gets the kind of the return node.
23+ */
24+ DataFlowImplCommon:: ReturnKindExt getKind ( ) { result = kind }
25+ }
26+
27+ bindingset [ c]
28+ private signature string printCallableParamSig ( Callable c , ParameterPosition p ) ;
29+
30+ private module PrintReturnNodeExt< printCallableParamSig / 2 printCallableParam> {
31+ string getOutput ( ReturnNodeExt node ) {
32+ node .getKind ( ) instanceof DataFlowImplCommon:: ValueReturnKind and
2333 result = "ReturnValue"
2434 or
2535 exists ( ParameterPosition pos |
26- pos = kind .( DataFlowImplCommon:: ParamUpdateReturnKind ) .getPosition ( ) and
27- result = paramReturnNodeAsOutput ( returnNodeEnclosingCallable ( this ) , pos )
36+ pos = node . getKind ( ) .( DataFlowImplCommon:: ParamUpdateReturnKind ) .getPosition ( ) and
37+ result = printCallableParam ( returnNodeEnclosingCallable ( node ) , pos )
2838 )
2939 }
3040}
3141
42+ string getOutput ( ReturnNodeExt node ) {
43+ result = PrintReturnNodeExt< paramReturnNodeAsOutput / 2 > :: getOutput ( node )
44+ }
45+
46+ string getContentOutput ( ReturnNodeExt node ) {
47+ result = PrintReturnNodeExt< paramReturnNodeAsContentOutput / 2 > :: getOutput ( node )
48+ }
49+
3250class DataFlowSummaryTargetApi extends SummaryTargetApi {
3351 DataFlowSummaryTargetApi ( ) { not isUninterestingForDataFlowModels ( this ) }
3452}
@@ -71,7 +89,8 @@ private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2
7189 * Holds if content `c` is either a field, a synthetic field or language specific
7290 * content of a relevant type or a container like content.
7391 */
74- private predicate isRelevantContent ( DataFlow:: ContentSet c ) {
92+ pragma [ nomagic]
93+ private predicate isRelevantContent0 ( DataFlow:: ContentSet c ) {
7594 isRelevantTypeInContent ( c ) or
7695 containerContent ( c )
7796}
@@ -85,6 +104,16 @@ string parameterNodeAsInput(DataFlow::ParameterNode p) {
85104 result = qualifierString ( ) and p instanceof InstanceParameterNode
86105}
87106
107+ /**
108+ * Gets the MaD string representation of the parameter `p`
109+ * when used in content flow.
110+ */
111+ string parameterNodeAsContentInput ( DataFlow:: ParameterNode p ) {
112+ result = parameterContentAccess ( p .asParameter ( ) )
113+ or
114+ result = qualifierString ( ) and p instanceof InstanceParameterNode
115+ }
116+
88117/**
89118 * Gets the MaD input string representation of `source`.
90119 */
@@ -170,7 +199,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
170199 ) {
171200 exists ( DataFlow:: ContentSet c |
172201 DataFlowImplCommon:: store ( node1 , c .getAStoreContent ( ) , node2 , _, _) and
173- isRelevantContent ( c ) and
202+ isRelevantContent0 ( c ) and
174203 (
175204 state1 instanceof TaintRead and state2 .( TaintStore ) .getStep ( ) = 1
176205 or
@@ -180,7 +209,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
180209 or
181210 exists ( DataFlow:: ContentSet c |
182211 DataFlowPrivate:: readStep ( node1 , c , node2 ) and
183- isRelevantContent ( c ) and
212+ isRelevantContent0 ( c ) and
184213 state1 .( TaintRead ) .getStep ( ) + 1 = state2 .( TaintRead ) .getStep ( )
185214 )
186215 }
@@ -196,14 +225,17 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
196225
197226module PropagateFlow = TaintTracking:: GlobalWithState< PropagateFlowConfig > ;
198227
228+ /**
229+ * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
230+ */
199231string captureThroughFlow0 (
200232 DataFlowSummaryTargetApi api , DataFlow:: ParameterNode p , ReturnNodeExt returnNodeExt
201233) {
202234 exists ( string input , string output |
203235 p .getEnclosingCallable ( ) = api and
204236 returnNodeExt .( DataFlow:: Node ) .getEnclosingCallable ( ) = api and
205237 input = parameterNodeAsInput ( p ) and
206- output = returnNodeExt . getOutput ( ) and
238+ output = getOutput ( returnNodeExt ) and
207239 input != output and
208240 result = Printing:: asTaintModel ( api , input , output )
209241 )
@@ -219,6 +251,69 @@ string captureThroughFlow(DataFlowSummaryTargetApi api) {
219251 )
220252}
221253
254+ private module PropagateContentFlowConfig implements ContentDataFlow:: ConfigSig {
255+ predicate isSource ( DataFlow:: Node source ) {
256+ source instanceof DataFlow:: ParameterNode and
257+ source .getEnclosingCallable ( ) instanceof DataFlowSummaryTargetApi
258+ }
259+
260+ predicate isSink ( DataFlow:: Node sink ) {
261+ sink instanceof ReturnNodeExt and
262+ sink .getEnclosingCallable ( ) instanceof DataFlowSummaryTargetApi
263+ }
264+
265+ predicate isAdditionalFlowStep = isAdditionalContentFlowStep / 2 ;
266+
267+ predicate isBarrier ( DataFlow:: Node n ) {
268+ exists ( Type t | t = n .getType ( ) and not isRelevantType ( t ) )
269+ }
270+
271+ int accessPathLimit ( ) { result = 2 }
272+
273+ predicate isRelevantContent ( DataFlow:: ContentSet s ) { isRelevantContent0 ( s ) }
274+
275+ DataFlow:: FlowFeature getAFeature ( ) {
276+ result instanceof DataFlow:: FeatureEqualSourceSinkCallContext
277+ }
278+ }
279+
280+ private module PropagateContentFlow = ContentDataFlow:: Global< PropagateContentFlowConfig > ;
281+
282+ private string getContent ( PropagateContentFlow:: AccessPath ap , int i ) {
283+ exists ( ContentSet head , PropagateContentFlow:: AccessPath tail |
284+ head = ap .getHead ( ) and
285+ tail = ap .getTail ( )
286+ |
287+ i = 0 and
288+ result = "." + printContent ( head )
289+ or
290+ i > 0 and result = getContent ( tail , i - 1 )
291+ )
292+ }
293+
294+ private string printStoreAccessPath ( PropagateContentFlow:: AccessPath ap ) {
295+ result = concat ( int i | | getContent ( ap , i ) , "" order by i )
296+ }
297+
298+ private string printReadAccessPath ( PropagateContentFlow:: AccessPath ap ) {
299+ result = concat ( int i | | getContent ( ap , i ) , "" order by i desc )
300+ }
301+
302+ string captureContentFlow ( DataFlowSummaryTargetApi api ) {
303+ exists (
304+ DataFlow:: ParameterNode p , ReturnNodeExt returnNodeExt , string input , string output ,
305+ PropagateContentFlow:: AccessPath reads , PropagateContentFlow:: AccessPath stores ,
306+ boolean preservesValue
307+ |
308+ PropagateContentFlow:: flow ( p , reads , returnNodeExt , stores , preservesValue ) and
309+ returnNodeExt .getEnclosingCallable ( ) = api and
310+ input = parameterNodeAsContentInput ( p ) + printReadAccessPath ( reads ) and
311+ output = getContentOutput ( returnNodeExt ) + printStoreAccessPath ( stores ) and
312+ input != output and
313+ result = Printing:: asModel ( api , input , output , preservesValue )
314+ )
315+ }
316+
222317/**
223318 * A dataflow configuration used for finding new sources.
224319 * The sources are the already known existing sources and the sinks are the API return nodes.
@@ -261,7 +356,7 @@ string captureSource(DataFlowSourceTargetApi api) {
261356 ExternalFlow:: sourceNode ( source , kind ) and
262357 api = sink .getEnclosingCallable ( ) and
263358 not irrelevantSourceSinkApi ( source .getEnclosingCallable ( ) , api ) and
264- result = Printing:: asSourceModel ( api , sink . getOutput ( ) , kind )
359+ result = Printing:: asSourceModel ( api , getOutput ( sink ) , kind )
265360 )
266361}
267362
0 commit comments