@@ -3729,7 +3729,7 @@ private predicate directReach(PathNode n) {
3729
3729
n instanceof PathNodeSink or directReach ( n .getASuccessor ( ) )
3730
3730
}
3731
3731
3732
- /** Holds if `n` can reach a sink or is used in a subpath. */
3732
+ /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink . */
3733
3733
private predicate reach ( PathNode n ) { directReach ( n ) or Subpaths:: retReach ( n ) }
3734
3734
3735
3735
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
@@ -3742,14 +3742,25 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
3742
3742
*/
3743
3743
module PathGraph {
3744
3744
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
3745
- query predicate edges ( PathNode a , PathNode b ) { a .getASuccessor ( ) = b and reach ( b ) }
3745
+ query predicate edges ( PathNode a , PathNode b ) { a .getASuccessor ( ) = b and reach ( a ) and reach ( b ) }
3746
3746
3747
3747
/** Holds if `n` is a node in the graph of data flow path explanations. */
3748
3748
query predicate nodes ( PathNode n , string key , string val ) {
3749
3749
reach ( n ) and key = "semmle.label" and val = n .toString ( )
3750
3750
}
3751
3751
3752
- query predicate subpaths = Subpaths:: subpaths / 4 ;
3752
+ /**
3753
+ * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
3754
+ * a subpath between `par` and `ret` with the connecting edges `arg -> par` and
3755
+ * `ret -> out` is summarized as the edge `arg -> out`.
3756
+ */
3757
+ query predicate subpaths ( PathNode arg , PathNode par , PathNode ret , PathNode out ) {
3758
+ Subpaths:: subpaths ( arg , par , ret , out ) and
3759
+ reach ( arg ) and
3760
+ reach ( par ) and
3761
+ reach ( ret ) and
3762
+ reach ( out )
3763
+ }
3753
3764
}
3754
3765
3755
3766
/**
@@ -4169,24 +4180,25 @@ private module Subpaths {
4169
4180
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
4170
4181
* `ret -> out` is summarized as the edge `arg -> out`.
4171
4182
*/
4172
- predicate subpaths ( PathNode arg , PathNodeImpl par , PathNodeImpl ret , PathNodeMid out ) {
4173
- exists ( ParamNodeEx p , NodeEx o , FlowState sout , AccessPath apout |
4183
+ predicate subpaths ( PathNode arg , PathNodeImpl par , PathNodeImpl ret , PathNode out ) {
4184
+ exists ( ParamNodeEx p , NodeEx o , FlowState sout , AccessPath apout , PathNodeMid out0 |
4174
4185
pragma [ only_bind_into ] ( arg ) .getASuccessor ( ) = par and
4175
- pragma [ only_bind_into ] ( arg ) .getASuccessor ( ) = out and
4186
+ pragma [ only_bind_into ] ( arg ) .getASuccessor ( ) = out0 and
4176
4187
subpaths03 ( arg , p , localStepToHidden * ( ret ) , o , sout , apout ) and
4177
4188
not ret .isHidden ( ) and
4178
4189
par .getNodeEx ( ) = p and
4179
- out .getNodeEx ( ) = o and
4180
- out .getState ( ) = sout and
4181
- out .getAp ( ) = apout
4190
+ out0 .getNodeEx ( ) = o and
4191
+ out0 .getState ( ) = sout and
4192
+ out0 .getAp ( ) = apout and
4193
+ ( out = out0 or out = out0 .projectToSink ( ) )
4182
4194
)
4183
4195
}
4184
4196
4185
4197
/**
4186
- * Holds if `n` can reach a return node in a summarized subpath.
4198
+ * Holds if `n` can reach a return node in a summarized subpath that can reach a sink .
4187
4199
*/
4188
4200
predicate retReach ( PathNode n ) {
4189
- subpaths ( _, _, n , _ )
4201
+ exists ( PathNode out | subpaths ( _, _, n , out ) | directReach ( out ) or retReach ( out ) )
4190
4202
or
4191
4203
exists ( PathNode mid |
4192
4204
retReach ( mid ) and
0 commit comments