@@ -943,10 +943,36 @@ private predicate isLive() { exists(DataFlow::Configuration cfg | isSource(_, cf
943943 * A data flow node on an inter-procedural path from a source.
944944 */
945945private newtype TPathNode =
946+ MkSourceNode ( DataFlow:: Node nd , DataFlow:: Configuration cfg ) { isSourceNode ( nd , cfg , _) }
947+ or
946948 MkMidNode ( DataFlow:: Node nd , DataFlow:: Configuration cfg , PathSummary summary ) {
947949 isLive ( ) and
948950 onPath ( nd , cfg , summary )
949951 }
952+ or
953+ MkSinkNode ( DataFlow:: Node nd , DataFlow:: Configuration cfg ) { isSinkNode ( nd , cfg , _) }
954+
955+ /**
956+ * Holds if `nd` is a source node for configuration `cfg`, and there is a path from `nd` to a sink
957+ * with the given `summary`.
958+ */
959+ private predicate isSourceNode ( DataFlow:: Node nd , DataFlow:: Configuration cfg , PathSummary summary ) {
960+ exists ( FlowLabel lbl | summary = PathSummary:: level ( lbl ) |
961+ isSource ( nd , cfg , lbl ) and
962+ isLive ( ) and
963+ onPath ( nd , cfg , summary )
964+ )
965+ }
966+
967+ /**
968+ * Holds if `nd` is a sink node for configuration `cfg`, and there is a path from a source to `nd`
969+ * with the given `summary`.
970+ */
971+ private predicate isSinkNode ( DataFlow:: Node nd , DataFlow:: Configuration cfg , PathSummary summary ) {
972+ isSink ( nd , cfg , summary .getEndLabel ( ) ) and
973+ isLive ( ) and
974+ onPath ( nd , cfg , summary )
975+ }
950976
951977/**
952978 * Maps `cfg` to itself.
@@ -958,25 +984,39 @@ bindingset[cfg, result]
958984private DataFlow:: Configuration id ( DataFlow:: Configuration cfg ) { result >= cfg and cfg >= result }
959985
960986/**
961- * A data flow node on an inter-procedural path from a source to a sink.
987+ * A data-flow node on an inter-procedural path from a source to a sink.
988+ *
989+ * A path node wraps a data-flow node `nd` and a data-flow configuration `cfg` such that `nd` is
990+ * on a path from a source to a sink under `cfg`.
962991 *
963- * A path node is a triple `(nd, cfg, summary)` where `nd` is a data flow node and `cfg`
964- * is a data flow tracking configuration such that `nd` is on a path from a source to a
965- * sink under `cfg` summarized by `summary`.
992+ * There are three kinds of path nodes:
993+ *
994+ * - source nodes: wrapping a source node and a configuration such that there is a path from that
995+ * source to some sink under the configuration;
996+ * - sink nodes: wrapping a sink node and a configuration such that there is a path from some source
997+ * to that sink under the configuration;
998+ * - mid nodes: wrapping a node, a configuration and a path summary such that there is a path from
999+ * some source to the node with the given summary that can be extended to a path to some sink node,
1000+ * all under the configuration.
9661001 */
9671002class PathNode extends TPathNode {
9681003 DataFlow:: Node nd ;
9691004 Configuration cfg ;
9701005
9711006 PathNode ( ) {
972- this = MkMidNode ( nd , cfg , _)
1007+ this = MkSourceNode ( nd , cfg ) or
1008+ this = MkMidNode ( nd , cfg , _) or
1009+ this = MkSinkNode ( nd , cfg )
9731010 }
9741011
9751012 /** Holds if this path node wraps data-flow node `nd` and configuration `c`. */
9761013 predicate wraps ( DataFlow:: Node n , DataFlow:: Configuration c ) {
9771014 nd = n and cfg = c
9781015 }
9791016
1017+ /** Gets the underlying configuration of this path node. */
1018+ DataFlow:: Configuration getConfiguration ( ) { result = cfg }
1019+
9801020 /** Gets the underlying data-flow node of this path node. */
9811021 DataFlow:: Node getNode ( ) { result = nd }
9821022
@@ -1004,11 +1044,22 @@ class PathNode extends TPathNode {
10041044
10051045private PathNode getASuccessor ( PathNode pnd ) {
10061046 exists ( DataFlow:: Node nd , Configuration cfg , PathSummary summary |
1047+ // source node to mid node
1048+ pnd = MkSourceNode ( nd , cfg ) and
1049+ isSourceNode ( nd , cfg , summary ) and
1050+ result = MkMidNode ( nd , cfg , summary )
1051+ or
1052+ // mid node to mid node
10071053 pnd = MkMidNode ( nd , cfg , summary ) and
10081054 exists ( DataFlow:: Node succ , PathSummary newSummary |
10091055 flowStep ( nd , id ( cfg ) , succ , newSummary ) and
10101056 result = MkMidNode ( succ , id ( cfg ) , summary .append ( newSummary ) )
10111057 )
1058+ or
1059+ // mid node to sink node
1060+ pnd = MkMidNode ( nd , cfg , summary ) and
1061+ isSinkNode ( nd , cfg , summary ) and
1062+ result = MkSinkNode ( nd , cfg )
10121063 )
10131064}
10141065
@@ -1029,9 +1080,6 @@ class MidPathNode extends PathNode, MkMidNode {
10291080
10301081 MidPathNode ( ) { this = MkMidNode ( nd , cfg , summary ) }
10311082
1032- /** Gets the underlying configuration of this path node. */
1033- DataFlow:: Configuration getConfiguration ( ) { result = cfg }
1034-
10351083 /** Gets the summary of the path underlying this path node. */
10361084 PathSummary getPathSummary ( ) { result = summary }
10371085
@@ -1047,31 +1095,27 @@ class MidPathNode extends PathNode, MkMidNode {
10471095 // Skip to the top of big left-leaning string concatenation trees.
10481096 nd = any ( AddExpr add ) .flow ( ) and
10491097 nd = any ( AddExpr add ) .getAnOperand ( ) .flow ( )
1098+ or
1099+ // Skip mid node immediately following a source node
1100+ exists ( MkSourceNode ( nd , cfg ) )
1101+ or
1102+ // Skip mid node immediately preceding a sink node
1103+ exists ( MkSinkNode ( nd , cfg ) )
10501104 }
10511105}
10521106
10531107/**
10541108 * A path node corresponding to a flow source.
10551109 */
1056- class SourcePathNode extends PathNode {
1057- SourcePathNode ( ) {
1058- exists ( FlowLabel lbl |
1059- this = MkMidNode ( nd , cfg , PathSummary:: level ( lbl ) ) and
1060- isSource ( nd , cfg , lbl )
1061- )
1062- }
1110+ class SourcePathNode extends PathNode , MkSourceNode {
1111+ SourcePathNode ( ) { this = MkSourceNode ( nd , cfg ) }
10631112}
10641113
10651114/**
10661115 * A path node corresponding to a flow sink.
10671116 */
1068- class SinkPathNode extends PathNode {
1069- SinkPathNode ( ) {
1070- exists ( PathSummary summary |
1071- this = MkMidNode ( nd , cfg , summary ) and
1072- isSink ( nd , cfg , summary .getEndLabel ( ) )
1073- )
1074- }
1117+ class SinkPathNode extends PathNode , MkSinkNode {
1118+ SinkPathNode ( ) { this = MkSinkNode ( nd , cfg ) }
10751119}
10761120
10771121/**
@@ -1080,9 +1124,7 @@ class SinkPathNode extends PathNode {
10801124module PathGraph {
10811125 /** Holds if `nd` is a node in the graph of data flow path explanations. */
10821126 query predicate nodes ( PathNode nd ) {
1083- not nd .( MidPathNode ) .isHidden ( ) or
1084- nd instanceof SourcePathNode or
1085- nd instanceof SinkPathNode
1127+ not nd .( MidPathNode ) .isHidden ( )
10861128 }
10871129
10881130 /** Holds if `pred` → `succ` is an edge in the graph of data flow path explanations. */
0 commit comments