Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 278ea90

Browse files
author
Max Schaefer
committed
JavaScript: Collapse flow labels at start/end nodes to avoid duplication.
1 parent 3169622 commit 278ea90

4 files changed

Lines changed: 90 additions & 40 deletions

File tree

javascript/ql/src/Security/Summaries/ExtractFlowStepSummaries.ql

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ import PortalExitSource
1414
import PortalEntrySink
1515

1616
from
17-
TaintTracking::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Portal p1,
18-
Portal p2, DataFlow::FlowLabel lbl1, DataFlow::FlowLabel lbl2
17+
TaintTracking::Configuration cfg, DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink, Portal p1,
18+
Portal p2, DataFlow::FlowLabel lbl1, DataFlow::FlowLabel lbl2, DataFlow::MidPathNode last
1919
where
20-
cfg.hasFlowPath(source, sink) and
20+
cfg = source.getConfiguration() and
21+
last = source.getASuccessor*() and
22+
sink = last.getASuccessor() and
2123
p1 = source.getNode().(PortalExitSource).getPortal() and
2224
p2 = sink.getNode().(PortalEntrySink).getPortal() and
23-
lbl1 = sink.(DataFlow::MidPathNode).getPathSummary().getStartLabel() and
24-
lbl2 = sink.(DataFlow::MidPathNode).getPathSummary().getEndLabel() and
25+
lbl1 = last.getPathSummary().getStartLabel() and
26+
lbl2 = last.getPathSummary().getEndLabel() and
2527
// avoid constructing infeasible paths
26-
sink.(DataFlow::MidPathNode).getPathSummary().hasCall() = false and
27-
sink.(DataFlow::MidPathNode).getPathSummary().hasReturn() = false and
28+
last.getPathSummary().hasCall() = false and
29+
last.getPathSummary().hasReturn() = false and
2830
// restrict to steps flow function parameters to returns
2931
p1.(ParameterPortal).getBasePortal() = p2.(ReturnPortal).getBasePortal() and
3032
// restrict to data/taint flow

javascript/ql/src/Security/Summaries/ExtractSinkSummaries.ql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ import Configurations
1111
import PortalExitSource
1212
import SinkFromAnnotation
1313

14-
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Portal p
14+
from DataFlow::Configuration cfg, DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink,
15+
Portal p, DataFlow::MidPathNode last
1516
where
16-
cfg.hasFlowPath(source, sink) and
17+
cfg = source.getConfiguration() and
18+
last = source.getASuccessor*() and
19+
sink = last.getASuccessor() and
1720
p = source.getNode().(PortalExitSource).getPortal() and
1821
// avoid constructing infeasible paths
19-
sink.(DataFlow::MidPathNode).getPathSummary().hasReturn() = false
20-
select p.toString(), source.(DataFlow::MidPathNode).getPathSummary().getStartLabel().toString(), cfg.toString()
22+
last.getPathSummary().hasReturn() = false
23+
select p.toString(), last.getPathSummary().getStartLabel().toString(), cfg.toString()

javascript/ql/src/Security/Summaries/ExtractSourceSummaries.ql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ import Configurations
1111
import PortalEntrySink
1212
import SourceFromAnnotation
1313

14-
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Portal p
14+
from DataFlow::Configuration cfg, DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink,
15+
Portal p, DataFlow::MidPathNode last
1516
where
16-
cfg.hasFlowPath(source, sink) and
17+
cfg = source.getConfiguration() and
18+
last = source.getASuccessor*() and
19+
sink = last.getASuccessor() and
1720
p = sink.getNode().(PortalEntrySink).getPortal() and
1821
// avoid constructing infeasible paths
19-
sink.(DataFlow::MidPathNode).getPathSummary().hasCall() = false
20-
select p.toString(), sink.(DataFlow::MidPathNode).getPathSummary().getEndLabel().toString(), cfg.toString()
22+
last.getPathSummary().hasCall() = false
23+
select p.toString(), last.getPathSummary().getEndLabel().toString(), cfg.toString()

javascript/ql/src/semmle/javascript/dataflow/Configuration.qll

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
945945
private 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]
958984
private 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
*/
9671002
class 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

10051045
private 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 {
10801124
module 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

Comments
 (0)