66private import CaptureModelsSpecific
77private import CaptureModelsPrinting
88
9+ /**
10+ * A node from which flow can return to the caller. This is either a regular
11+ * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
12+ */
13+ private class ReturnNodeExt extends DataFlow:: Node {
14+ private DataFlowImplCommon:: ReturnKindExt kind ;
15+
16+ ReturnNodeExt ( ) {
17+ kind = DataFlowImplCommon:: getValueReturnPosition ( this ) .getKind ( ) or
18+ kind = DataFlowImplCommon:: getParamReturnPosition ( this , _) .getKind ( )
19+ }
20+
21+ string getOutput ( ) {
22+ kind instanceof DataFlowImplCommon:: ValueReturnKind and
23+ result = "ReturnValue"
24+ or
25+ exists ( ParameterPosition pos |
26+ pos = kind .( DataFlowImplCommon:: ParamUpdateReturnKind ) .getPosition ( ) and
27+ result = paramReturnNodeAsOutput ( returnNodeEnclosingCallable ( this ) , pos )
28+ )
29+ }
30+ }
31+
932class DataFlowTargetApi extends TargetApiSpecific {
1033 DataFlowTargetApi ( ) { not isUninterestingForDataFlowModels ( this ) }
1134}
@@ -65,7 +88,7 @@ string asInputArgument(DataFlow::Node source) { result = asInputArgumentSpecific
6588 * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`).
6689 */
6790string captureQualifierFlow ( TargetApiSpecific api ) {
68- exists ( DataFlowImplCommon :: ReturnNodeExt ret |
91+ exists ( ReturnNodeExt ret |
6992 api = returnNodeEnclosingCallable ( ret ) and
7093 isOwnInstanceAccessNode ( ret )
7194 ) and
@@ -130,7 +153,7 @@ module ThroughFlowConfig implements DataFlow::StateConfigSig {
130153 }
131154
132155 predicate isSink ( DataFlow:: Node sink , FlowState state ) {
133- sink instanceof DataFlowImplCommon :: ReturnNodeExt and
156+ sink instanceof ReturnNodeExt and
134157 not isOwnInstanceAccessNode ( sink ) and
135158 not exists ( captureQualifierFlow ( sink .asExpr ( ) .getEnclosingCallable ( ) ) ) and
136159 ( state instanceof TaintRead or state instanceof TaintStore )
@@ -171,14 +194,11 @@ private module ThroughFlow = TaintTracking::GlobalWithState<ThroughFlowConfig>;
171194 * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
172195 */
173196string captureThroughFlow ( DataFlowTargetApi api ) {
174- exists (
175- DataFlow:: ParameterNode p , DataFlowImplCommon:: ReturnNodeExt returnNodeExt , string input ,
176- string output
177- |
197+ exists ( DataFlow:: ParameterNode p , ReturnNodeExt returnNodeExt , string input , string output |
178198 ThroughFlow:: flow ( p , returnNodeExt ) and
179199 returnNodeExt .( DataFlow:: Node ) .getEnclosingCallable ( ) = api and
180200 input = parameterNodeAsInput ( p ) and
181- output = returnNodeAsOutput ( returnNodeExt ) and
201+ output = returnNodeExt . getOutput ( ) and
182202 input != output and
183203 result = ModelPrinting:: asTaintModel ( api , input , output )
184204 )
@@ -196,7 +216,7 @@ module FromSourceConfig implements DataFlow::ConfigSig {
196216
197217 predicate isSink ( DataFlow:: Node sink ) {
198218 exists ( DataFlowTargetApi c |
199- sink instanceof DataFlowImplCommon :: ReturnNodeExt and
219+ sink instanceof ReturnNodeExt and
200220 sink .getEnclosingCallable ( ) = c
201221 )
202222 }
@@ -214,12 +234,12 @@ private module FromSource = TaintTracking::Global<FromSourceConfig>;
214234 * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`.
215235 */
216236string captureSource ( DataFlowTargetApi api ) {
217- exists ( DataFlow:: Node source , DataFlow :: Node sink , string kind |
237+ exists ( DataFlow:: Node source , ReturnNodeExt sink , string kind |
218238 FromSource:: flow ( source , sink ) and
219239 ExternalFlow:: sourceNode ( source , kind ) and
220240 api = sink .getEnclosingCallable ( ) and
221241 isRelevantSourceKind ( kind ) and
222- result = ModelPrinting:: asSourceModel ( api , returnNodeAsOutput ( sink ) , kind )
242+ result = ModelPrinting:: asSourceModel ( api , sink . getOutput ( ) , kind )
223243 )
224244}
225245
0 commit comments