@@ -1046,6 +1046,102 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1046
1046
}
1047
1047
1048
1048
private module ReverseFlow {
1049
+ module Cand {
1050
+ /**
1051
+ * Holds if `p` can flow to `node` in the same callable using only
1052
+ * value-preserving steps.
1053
+ *
1054
+ * `read` indicates whether it is contents of `p` that can flow to `node`.
1055
+ */
1056
+ 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
+ )
1085
+ )
1086
+ }
1087
+
1088
+ pragma [ nomagic]
1089
+ private predicate parameterValueFlowArgCand ( ParamNode p , ArgNode arg ) {
1090
+ parameterValueFlowCand ( p , arg )
1091
+ }
1092
+
1093
+ pragma [ nomagic]
1094
+ predicate parameterValueFlowsToPreUpdateCand ( ParamNode p , PostUpdateNode n ) {
1095
+ parameterValueFlowCand ( p , n .getPreUpdateNode ( ) )
1096
+ }
1097
+
1098
+ /**
1099
+ * Holds if `p` can flow to a return node of kind `kind` in the same
1100
+ * callable using only value-preserving steps, not taking call contexts
1101
+ * into account.
1102
+ *
1103
+ * `read` indicates whether it is contents of `p` that can flow to the return
1104
+ * node.
1105
+ */
1106
+ predicate parameterValueFlowReturnCand ( ParamNode p , ReturnKind kind ) {
1107
+ exists ( ReturnNode ret |
1108
+ parameterValueFlowCand ( p , ret ) and
1109
+ kind = ret .getKind ( )
1110
+ )
1111
+ }
1112
+
1113
+ pragma [ nomagic]
1114
+ private predicate argumentValueFlowsThroughCand0 (
1115
+ DataFlowCall call , ArgNode arg , ReturnKind kind
1116
+ ) {
1117
+ exists ( ParamNode param | viableParamArg ( call , param , arg ) |
1118
+ parameterValueFlowReturnCand ( param , kind )
1119
+ )
1120
+ }
1121
+
1122
+ /**
1123
+ * Holds if `arg` flows to `out` through a call using only value-preserving steps,
1124
+ * not taking call contexts into account.
1125
+ *
1126
+ * `read` indicates whether it is contents of `arg` that can flow to `out`.
1127
+ */
1128
+ predicate argumentValueFlowsThroughCand ( ArgNode arg , Node out ) {
1129
+ exists ( DataFlowCall call , ReturnKind kind |
1130
+ argumentValueFlowsThroughCand0 ( call , arg , kind ) and
1131
+ out = getAnOutNode ( call , kind )
1132
+ )
1133
+ }
1134
+
1135
+ predicate cand ( ParamNode p , Node n ) {
1136
+ parameterValueFlowCand ( p , n ) and
1137
+ (
1138
+ parameterValueFlowReturnCand ( p , _)
1139
+ or
1140
+ parameterValueFlowsToPreUpdateCand ( p , _)
1141
+ )
1142
+ }
1143
+ }
1144
+
1049
1145
/**
1050
1146
* Holds if the local step from `arg` to `out` actually models a flow-through
1051
1147
* step.
@@ -2091,7 +2187,9 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
2091
2187
newtype TNodeEx =
2092
2188
TNodeNormal ( Node n ) or
2093
2189
TNodeImplicitRead ( Node n ) or // will be restricted to nodes with actual implicit reads in `DataFlowImpl.qll`
2094
- TNodeReverse ( Node n , Boolean allowFwdFlowOut )
2190
+ TNodeReverse ( Node n , Boolean allowFwdFlowOut ) {
2191
+ ReverseFlow:: Cand:: cand ( _, n ) or n = any ( PostUpdateNode p ) .getPreUpdateNode ( )
2192
+ }
2095
2193
2096
2194
/**
2097
2195
* Holds if data can flow in one local step from `node1` to `node2`.
0 commit comments