@@ -878,15 +878,19 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
878
878
string toString ( ) {
879
879
result = this .asNode ( ) .toString ( )
880
880
or
881
- exists ( Node n | this .isImplicitReadNode ( n ) | result = n . toString ( ) + " [Ext]" )
881
+ exists ( Node n | this .isImplicitReadNode ( n ) | result = n + " [Ext]" )
882
882
or
883
- result = this .asNodeReverse ( _) .toString ( ) + " [Reverse]"
883
+ result = this .asNodeReverse ( _) + " [Reverse]"
884
+ or
885
+ result = this .asNodeReverseReturnPosition ( ) + " [ReverseReturn]"
884
886
}
885
887
886
888
Node asNode ( ) { this = TNodeNormal ( result ) }
887
889
888
890
Node asNodeReverse ( boolean allowFwdFlowOut ) { this = TNodeReverse ( result , allowFwdFlowOut ) }
889
891
892
+ ReturnPosition asNodeReverseReturnPosition ( ) { this = TNodeReverseReturn ( result ) }
893
+
890
894
/** Gets the corresponding Node if this is a normal node or its post-implicit read node. */
891
895
Node asNodeOrImplicitRead ( ) { this = TNodeNormal ( result ) or this = TNodeImplicitRead ( result ) }
892
896
@@ -901,6 +905,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
901
905
pragma [ nomagic]
902
906
private DataFlowCallable getEnclosingCallable0 ( ) {
903
907
nodeEnclosingCallable ( this .projectToNode ( ) , result )
908
+ or
909
+ result = this .asNodeReverseReturnPosition ( ) .getCallable ( )
904
910
}
905
911
906
912
pragma [ inline]
@@ -915,6 +921,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
915
921
nodeDataFlowType ( this .asNodeReverse ( _) , result )
916
922
or
917
923
isTopType ( result ) and this .isImplicitReadNode ( _)
924
+ or
925
+ result = this .( ReverseFlow:: ReverseParamNodeEx ) .getAReturnNode ( ) .getDataFlowType0 ( )
918
926
}
919
927
920
928
pragma [ inline]
@@ -1047,52 +1055,71 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1047
1055
1048
1056
private module ReverseFlow {
1049
1057
module Cand {
1058
+ // todo: check types
1050
1059
/**
1051
1060
* Holds if `p` can flow to `node` in the same callable using only
1052
1061
* value-preserving steps.
1053
1062
*
1054
1063
* `read` indicates whether it is contents of `p` that can flow to `node`.
1055
1064
*/
1056
1065
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 ) )
1085
1112
)
1086
1113
}
1087
1114
1088
1115
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 )
1091
1118
}
1092
1119
1093
1120
pragma [ nomagic]
1094
1121
predicate parameterValueFlowsToPreUpdateCand ( ParamNode p , PostUpdateNode n ) {
1095
- parameterValueFlowCand ( p , n .getPreUpdateNode ( ) )
1122
+ parameterValueFlowCand ( p , _ , n .getPreUpdateNode ( ) )
1096
1123
}
1097
1124
1098
1125
/**
@@ -1103,20 +1130,19 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1103
1130
* `read` indicates whether it is contents of `p` that can flow to the return
1104
1131
* node.
1105
1132
*/
1106
- predicate parameterValueFlowReturnCand ( ParamNode p , ReturnKind kind ) {
1133
+ predicate parameterValueFlowReturnCand ( ParamNode p , DataFlowType t , ReturnKind kind ) {
1107
1134
exists ( ReturnNode ret |
1108
- parameterValueFlowCand ( p , ret ) and
1135
+ parameterValueFlowCand ( p , t , ret ) and
1109
1136
kind = ret .getKind ( )
1110
1137
)
1111
1138
}
1112
1139
1113
1140
pragma [ nomagic]
1114
1141
private predicate argumentValueFlowsThroughCand0 (
1115
- DataFlowCall call , ArgNode arg , ReturnKind kind
1142
+ DataFlowCall call , ParamNode param , ArgNode arg , DataFlowType t , ReturnKind kind
1116
1143
) {
1117
- exists ( ParamNode param | viableParamArg ( call , param , arg ) |
1118
- parameterValueFlowReturnCand ( param , kind )
1119
- )
1144
+ viableParamArg ( call , param , arg ) and
1145
+ parameterValueFlowReturnCand ( param , t , kind )
1120
1146
}
1121
1147
1122
1148
/**
@@ -1125,17 +1151,17 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1125
1151
*
1126
1152
* `read` indicates whether it is contents of `arg` that can flow to `out`.
1127
1153
*/
1128
- predicate argumentValueFlowsThroughCand ( ArgNode arg , Node out ) {
1154
+ predicate argumentValueFlowsThroughCand ( ArgNode arg , ParamNode p , DataFlowType t , Node out ) {
1129
1155
exists ( DataFlowCall call , ReturnKind kind |
1130
- argumentValueFlowsThroughCand0 ( call , arg , kind ) and
1156
+ argumentValueFlowsThroughCand0 ( call , arg , p , t , kind ) and
1131
1157
out = getAnOutNode ( call , kind )
1132
1158
)
1133
1159
}
1134
1160
1135
1161
predicate cand ( ParamNode p , Node n ) {
1136
- parameterValueFlowCand ( p , n ) and
1162
+ parameterValueFlowCand ( p , _ , n ) and
1137
1163
(
1138
- parameterValueFlowReturnCand ( p , _)
1164
+ parameterValueFlowReturnCand ( p , _, _ )
1139
1165
or
1140
1166
parameterValueFlowsToPreUpdateCand ( p , _)
1141
1167
)
@@ -1178,6 +1204,9 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1178
1204
node2 .asNode ( ) .( PostUpdateNode ) .getPreUpdateNode ( ) = n2
1179
1205
)
1180
1206
or
1207
+ node2 = node1 .( ReverseParamNodeEx ) .getAReturnNode ( ) and
1208
+ model = ""
1209
+ or
1181
1210
node1 .asNode ( ) .( PostUpdateNode ) .getPreUpdateNode ( ) = node2 .asNodeReverse ( true ) and
1182
1211
model = ""
1183
1212
}
@@ -1240,18 +1269,23 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1240
1269
}
1241
1270
}
1242
1271
1243
- final class ReverseParamNodeEx extends ParamNodeEx {
1272
+ final class ReverseParamNodeEx extends ParamNodeEx , TNodeReverseReturn {
1244
1273
private DataFlowCallable c_ ;
1245
1274
private ParameterPositionEx pos_ ;
1246
1275
1247
1276
ReverseParamNodeEx ( ) {
1248
1277
exists ( ReturnPosition pos |
1249
- pos = getValueReturnPosition ( this .asNodeReverse ( false ) ) and
1278
+ this = TNodeReverseReturn ( pos ) and
1279
+ // pos = getValueReturnPosition(this.asNodeReverse(false)) and
1250
1280
c_ = pos .getCallable ( ) and
1251
1281
pos_ .asReturnKind ( ) = pos .getKind ( )
1252
1282
)
1253
1283
}
1254
1284
1285
+ NodeEx getAReturnNode ( ) {
1286
+ this = TNodeReverseReturn ( getValueReturnPosition ( result .asNodeReverse ( false ) ) )
1287
+ }
1288
+
1255
1289
override predicate isParameterOf ( DataFlowCallable c , ParameterPositionEx pos ) {
1256
1290
c = c_ and pos = pos_
1257
1291
}
@@ -1349,6 +1383,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1349
1383
nodeIsHidden ( [ n .asNode ( ) , n .asNodeReverse ( _) ] )
1350
1384
or
1351
1385
n instanceof TNodeImplicitRead
1386
+ or
1387
+ n instanceof ReverseFlow:: ReverseParamNodeEx
1352
1388
}
1353
1389
1354
1390
cached
@@ -2191,6 +2227,13 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
2191
2227
TNodeReverse ( Node n , Boolean allowFwdFlowOut ) {
2192
2228
( ReverseFlow:: Cand:: cand ( _, n ) or n = any ( PostUpdateNode p ) .getPreUpdateNode ( ) ) and
2193
2229
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
+ )
2194
2237
}
2195
2238
2196
2239
/**
0 commit comments