@@ -878,15 +878,19 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
878878 string toString ( ) {
879879 result = this .asNode ( ) .toString ( )
880880 or
881- exists ( Node n | this .isImplicitReadNode ( n ) | result = n . toString ( ) + " [Ext]" )
881+ exists ( Node n | this .isImplicitReadNode ( n ) | result = n + " [Ext]" )
882882 or
883- result = this .asNodeReverse ( _) .toString ( ) + " [Reverse]"
883+ result = this .asNodeReverse ( _) + " [Reverse]"
884+ or
885+ result = this .asNodeReverseReturnPosition ( ) + " [ReverseReturn]"
884886 }
885887
886888 Node asNode ( ) { this = TNodeNormal ( result ) }
887889
888890 Node asNodeReverse ( boolean allowFwdFlowOut ) { this = TNodeReverse ( result , allowFwdFlowOut ) }
889891
892+ ReturnPosition asNodeReverseReturnPosition ( ) { this = TNodeReverseReturn ( result ) }
893+
890894 /** Gets the corresponding Node if this is a normal node or its post-implicit read node. */
891895 Node asNodeOrImplicitRead ( ) { this = TNodeNormal ( result ) or this = TNodeImplicitRead ( result ) }
892896
@@ -901,6 +905,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
901905 pragma [ nomagic]
902906 private DataFlowCallable getEnclosingCallable0 ( ) {
903907 nodeEnclosingCallable ( this .projectToNode ( ) , result )
908+ or
909+ result = this .asNodeReverseReturnPosition ( ) .getCallable ( )
904910 }
905911
906912 pragma [ inline]
@@ -915,6 +921,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
915921 nodeDataFlowType ( this .asNodeReverse ( _) , result )
916922 or
917923 isTopType ( result ) and this .isImplicitReadNode ( _)
924+ or
925+ result = this .( ReverseFlow:: ReverseParamNodeEx ) .getAReturnNode ( ) .getDataFlowType0 ( )
918926 }
919927
920928 pragma [ inline]
@@ -1047,52 +1055,71 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
10471055
10481056 private module ReverseFlow {
10491057 module Cand {
1058+ // todo: check types
10501059 /**
10511060 * Holds if `p` can flow to `node` in the same callable using only
10521061 * value-preserving steps.
10531062 *
10541063 * `read` indicates whether it is contents of `p` that can flow to `node`.
10551064 */
10561065 pragma [ nomagic]
1057- private predicate parameterValueFlowCand ( ParamNode p , Node node ) {
1058- (
1059- p = node
1060- or
1061- // local flow
1062- exists ( Node mid |
1063- parameterValueFlowCand ( p , mid ) and
1064- simpleLocalFlowStep ( mid , node , _) and
1065- validParameterAliasStep ( mid , node )
1066- )
1067- or
1068- // store
1069- exists ( Node mid |
1070- parameterValueFlowCand ( p , mid ) and
1071- Lang:: storeStep ( mid , _, node )
1072- )
1073- or
1074- // read
1075- exists ( Node mid |
1076- parameterValueFlowCand ( p , mid ) and
1077- Lang:: readStep ( mid , _, node )
1078- )
1079- or
1080- // flow through
1081- exists ( ArgNode arg |
1082- parameterValueFlowArgCand ( p , arg ) and
1083- argumentValueFlowsThroughCand ( arg , node )
1084- )
1066+ private predicate parameterValueFlowCand ( ParamNode p , DataFlowType t , Node node ) {
1067+ parameterValueFlowCand0 ( p , t , node ) and
1068+ if node instanceof CastingNode
1069+ then compatibleTypesFilter ( t , getNodeDataFlowType ( node ) )
1070+ else any ( )
1071+ }
1072+
1073+ /**
1074+ * Holds if `p` can flow to `node` in the same callable using only
1075+ * value-preserving steps.
1076+ *
1077+ * `read` indicates whether it is contents of `p` that can flow to `node`.
1078+ */
1079+ pragma [ nomagic]
1080+ private predicate parameterValueFlowCand0 ( ParamNode p , DataFlowType t , Node node ) {
1081+ p = node and
1082+ t = getNodeDataFlowType ( node )
1083+ or
1084+ // local flow
1085+ exists ( Node mid |
1086+ parameterValueFlowCand ( p , t , mid ) and
1087+ simpleLocalFlowStep ( mid , node , _) and
1088+ validParameterAliasStep ( mid , node )
1089+ )
1090+ or
1091+ // store
1092+ exists ( Node mid , DataFlowType t0 |
1093+ parameterValueFlowCand ( p , t0 , mid ) and
1094+ Lang:: storeStep ( mid , _, node ) and
1095+ t = getNodeDataFlowType ( node ) and
1096+ compatibleTypes ( t0 , pragma [ only_bind_out ] ( getNodeDataFlowType ( mid ) ) )
1097+ )
1098+ or
1099+ // read
1100+ exists ( Node mid , DataFlowType t0 |
1101+ parameterValueFlowCand ( p , t0 , mid ) and
1102+ Lang:: readStep ( mid , _, node ) and
1103+ t = getNodeDataFlowType ( node ) and
1104+ compatibleTypes ( t0 , pragma [ only_bind_out ] ( getNodeDataFlowType ( mid ) ) )
1105+ )
1106+ or
1107+ // flow through
1108+ exists ( ParamNode p0 , DataFlowType t0 , ArgNode arg |
1109+ parameterValueFlowArgCand ( p , t0 , arg ) and
1110+ argumentValueFlowsThroughCand ( arg , p0 , t , node ) and
1111+ compatibleTypes ( t0 , getNodeDataFlowType ( p0 ) )
10851112 )
10861113 }
10871114
10881115 pragma [ nomagic]
1089- private predicate parameterValueFlowArgCand ( ParamNode p , ArgNode arg ) {
1090- parameterValueFlowCand ( p , arg )
1116+ private predicate parameterValueFlowArgCand ( ParamNode p , DataFlowType t , ArgNode arg ) {
1117+ parameterValueFlowCand ( p , t , arg )
10911118 }
10921119
10931120 pragma [ nomagic]
10941121 predicate parameterValueFlowsToPreUpdateCand ( ParamNode p , PostUpdateNode n ) {
1095- parameterValueFlowCand ( p , n .getPreUpdateNode ( ) )
1122+ parameterValueFlowCand ( p , _ , n .getPreUpdateNode ( ) )
10961123 }
10971124
10981125 /**
@@ -1103,20 +1130,19 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
11031130 * `read` indicates whether it is contents of `p` that can flow to the return
11041131 * node.
11051132 */
1106- predicate parameterValueFlowReturnCand ( ParamNode p , ReturnKind kind ) {
1133+ predicate parameterValueFlowReturnCand ( ParamNode p , DataFlowType t , ReturnKind kind ) {
11071134 exists ( ReturnNode ret |
1108- parameterValueFlowCand ( p , ret ) and
1135+ parameterValueFlowCand ( p , t , ret ) and
11091136 kind = ret .getKind ( )
11101137 )
11111138 }
11121139
11131140 pragma [ nomagic]
11141141 private predicate argumentValueFlowsThroughCand0 (
1115- DataFlowCall call , ArgNode arg , ReturnKind kind
1142+ DataFlowCall call , ParamNode param , ArgNode arg , DataFlowType t , ReturnKind kind
11161143 ) {
1117- exists ( ParamNode param | viableParamArg ( call , param , arg ) |
1118- parameterValueFlowReturnCand ( param , kind )
1119- )
1144+ viableParamArg ( call , param , arg ) and
1145+ parameterValueFlowReturnCand ( param , t , kind )
11201146 }
11211147
11221148 /**
@@ -1125,17 +1151,17 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
11251151 *
11261152 * `read` indicates whether it is contents of `arg` that can flow to `out`.
11271153 */
1128- predicate argumentValueFlowsThroughCand ( ArgNode arg , Node out ) {
1154+ predicate argumentValueFlowsThroughCand ( ArgNode arg , ParamNode p , DataFlowType t , Node out ) {
11291155 exists ( DataFlowCall call , ReturnKind kind |
1130- argumentValueFlowsThroughCand0 ( call , arg , kind ) and
1156+ argumentValueFlowsThroughCand0 ( call , arg , p , t , kind ) and
11311157 out = getAnOutNode ( call , kind )
11321158 )
11331159 }
11341160
11351161 predicate cand ( ParamNode p , Node n ) {
1136- parameterValueFlowCand ( p , n ) and
1162+ parameterValueFlowCand ( p , _ , n ) and
11371163 (
1138- parameterValueFlowReturnCand ( p , _)
1164+ parameterValueFlowReturnCand ( p , _, _ )
11391165 or
11401166 parameterValueFlowsToPreUpdateCand ( p , _)
11411167 )
@@ -1178,6 +1204,9 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
11781204 node2 .asNode ( ) .( PostUpdateNode ) .getPreUpdateNode ( ) = n2
11791205 )
11801206 or
1207+ node2 = node1 .( ReverseParamNodeEx ) .getAReturnNode ( ) and
1208+ model = ""
1209+ or
11811210 node1 .asNode ( ) .( PostUpdateNode ) .getPreUpdateNode ( ) = node2 .asNodeReverse ( true ) and
11821211 model = ""
11831212 }
@@ -1240,18 +1269,23 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
12401269 }
12411270 }
12421271
1243- final class ReverseParamNodeEx extends ParamNodeEx {
1272+ final class ReverseParamNodeEx extends ParamNodeEx , TNodeReverseReturn {
12441273 private DataFlowCallable c_ ;
12451274 private ParameterPositionEx pos_ ;
12461275
12471276 ReverseParamNodeEx ( ) {
12481277 exists ( ReturnPosition pos |
1249- pos = getValueReturnPosition ( this .asNodeReverse ( false ) ) and
1278+ this = TNodeReverseReturn ( pos ) and
1279+ // pos = getValueReturnPosition(this.asNodeReverse(false)) and
12501280 c_ = pos .getCallable ( ) and
12511281 pos_ .asReturnKind ( ) = pos .getKind ( )
12521282 )
12531283 }
12541284
1285+ NodeEx getAReturnNode ( ) {
1286+ this = TNodeReverseReturn ( getValueReturnPosition ( result .asNodeReverse ( false ) ) )
1287+ }
1288+
12551289 override predicate isParameterOf ( DataFlowCallable c , ParameterPositionEx pos ) {
12561290 c = c_ and pos = pos_
12571291 }
@@ -1349,6 +1383,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
13491383 nodeIsHidden ( [ n .asNode ( ) , n .asNodeReverse ( _) ] )
13501384 or
13511385 n instanceof TNodeImplicitRead
1386+ or
1387+ n instanceof ReverseFlow:: ReverseParamNodeEx
13521388 }
13531389
13541390 cached
@@ -2191,6 +2227,13 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
21912227 TNodeReverse ( Node n , Boolean allowFwdFlowOut ) {
21922228 ( ReverseFlow:: Cand:: cand ( _, n ) or n = any ( PostUpdateNode p ) .getPreUpdateNode ( ) ) and
21932229 if allowFwdFlowOut = false then ReverseFlow:: Cand:: cand ( _, n ) else any ( )
2230+ } or
2231+ TNodeReverseReturn ( ReturnPosition pos ) {
2232+ exists ( ParamNode p , ReturnKind kind |
2233+ pos .getKind ( ) .( ValueReturnKind ) .getKind ( ) = kind and
2234+ ReverseFlow:: Cand:: parameterValueFlowReturnCand ( p , _, kind ) and
2235+ pos .getCallable ( ) = getNodeEnclosingCallable ( p )
2236+ )
21942237 }
21952238
21962239 /**
0 commit comments