JavaScript: Factor out MidPathNode into its own class.

This commit is contained in:
Max Schaefer
2019-10-21 11:14:44 +01:00
parent 7c56c9f999
commit 316962233c
4 changed files with 57 additions and 38 deletions

View File

@@ -20,11 +20,11 @@ where
cfg.hasFlowPath(source, sink) and
p1 = source.getNode().(PortalExitSource).getPortal() and
p2 = sink.getNode().(PortalEntrySink).getPortal() and
lbl1 = sink.getPathSummary().getStartLabel() and
lbl2 = sink.getPathSummary().getEndLabel() and
lbl1 = sink.(DataFlow::MidPathNode).getPathSummary().getStartLabel() and
lbl2 = sink.(DataFlow::MidPathNode).getPathSummary().getEndLabel() and
// avoid constructing infeasible paths
sink.getPathSummary().hasCall() = false and
sink.getPathSummary().hasReturn() = false and
sink.(DataFlow::MidPathNode).getPathSummary().hasCall() = false and
sink.(DataFlow::MidPathNode).getPathSummary().hasReturn() = false and
// restrict to steps flow function parameters to returns
p1.(ParameterPortal).getBasePortal() = p2.(ReturnPortal).getBasePortal() and
// restrict to data/taint flow

View File

@@ -16,5 +16,5 @@ where
cfg.hasFlowPath(source, sink) and
p = source.getNode().(PortalExitSource).getPortal() and
// avoid constructing infeasible paths
sink.getPathSummary().hasReturn() = false
select p.toString(), source.getPathSummary().getStartLabel().toString(), cfg.toString()
sink.(DataFlow::MidPathNode).getPathSummary().hasReturn() = false
select p.toString(), source.(DataFlow::MidPathNode).getPathSummary().getStartLabel().toString(), cfg.toString()

View File

@@ -16,5 +16,5 @@ where
cfg.hasFlowPath(source, sink) and
p = sink.getNode().(PortalEntrySink).getPortal() and
// avoid constructing infeasible paths
sink.getPathSummary().hasCall() = false
select p.toString(), sink.getPathSummary().getEndLabel().toString(), cfg.toString()
sink.(DataFlow::MidPathNode).getPathSummary().hasCall() = false
select p.toString(), sink.(DataFlow::MidPathNode).getPathSummary().getEndLabel().toString(), cfg.toString()

View File

@@ -966,25 +966,20 @@ private DataFlow::Configuration id(DataFlow::Configuration cfg) { result >= cfg
*/
class PathNode extends TPathNode {
DataFlow::Node nd;
DataFlow::Configuration cfg;
PathSummary summary;
Configuration cfg;
PathNode() { this = MkMidNode(nd, cfg, summary) }
/** Gets the underlying data flow node of this path node. */
DataFlow::Node getNode() { result = nd }
/** Gets the underlying data flow tracking configuration of this path node. */
DataFlow::Configuration getConfiguration() { result = cfg }
/** Gets the summary of the path underlying this path node. */
PathSummary getPathSummary() { result = summary }
PathNode() {
this = MkMidNode(nd, cfg, _)
}
/** Holds if this path node wraps data-flow node `nd` and configuration `c`. */
predicate wraps(DataFlow::Node n, DataFlow::Configuration c) {
nd = n and cfg = c
}
/** Gets the underlying data-flow node of this path node. */
DataFlow::Node getNode() { result = nd }
/** Gets a successor node of this path node. */
final PathNode getASuccessor() {
result = getASuccessor(this)
@@ -1005,6 +1000,40 @@ class PathNode extends TPathNode {
) {
nd.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
private PathNode getASuccessor(PathNode pnd) {
exists(DataFlow::Node nd, Configuration cfg, PathSummary summary |
pnd = MkMidNode(nd, cfg, summary) and
exists(DataFlow::Node succ, PathSummary newSummary |
flowStep(nd, id(cfg), succ, newSummary) and
result = MkMidNode(succ, id(cfg), summary.append(newSummary))
)
)
}
private PathNode getASuccessorIfHidden(PathNode nd) {
nd.(MidPathNode).isHidden() and
result = getASuccessor(nd)
}
/**
* A path node corresponding to an intermediate node on a path from a source to a sink.
*
* A mid node is a triple `(nd, cfg, summary)` where `nd` is a data-flow node and `cfg`
* is a configuration such that `nd` is on a path from a source to a sink under `cfg`
* summarized by `summary`.
*/
class MidPathNode extends PathNode, MkMidNode {
PathSummary summary;
MidPathNode() { this = MkMidNode(nd, cfg, summary) }
/** Gets the underlying configuration of this path node. */
DataFlow::Configuration getConfiguration() { result = cfg }
/** Gets the summary of the path underlying this path node. */
PathSummary getPathSummary() { result = summary }
/**
* Holds if this node is hidden from paths in path explanation queries, except
@@ -1021,28 +1050,13 @@ class PathNode extends TPathNode {
}
}
private PathNode getASuccessor(PathNode pnd) {
exists(DataFlow::Node nd, Configuration cfg, PathSummary summary |
pnd = MkMidNode(nd, cfg, summary) and
exists(DataFlow::Node succ, PathSummary newSummary |
flowStep(nd, id(cfg), succ, newSummary) and
result = MkMidNode(succ, id(cfg), summary.append(newSummary))
)
)
}
private PathNode getASuccessorIfHidden(PathNode nd) {
nd.isHidden() and
result = getASuccessor(nd)
}
/**
* A path node corresponding to a flow source.
*/
class SourcePathNode extends PathNode {
SourcePathNode() {
exists(FlowLabel lbl |
summary = PathSummary::level(lbl) and
this = MkMidNode(nd, cfg, PathSummary::level(lbl)) and
isSource(nd, cfg, lbl)
)
}
@@ -1052,7 +1066,12 @@ class SourcePathNode extends PathNode {
* A path node corresponding to a flow sink.
*/
class SinkPathNode extends PathNode {
SinkPathNode() { isSink(nd, cfg, summary.getEndLabel()) }
SinkPathNode() {
exists(PathSummary summary |
this = MkMidNode(nd, cfg, summary) and
isSink(nd, cfg, summary.getEndLabel())
)
}
}
/**
@@ -1061,7 +1080,7 @@ class SinkPathNode extends PathNode {
module PathGraph {
/** Holds if `nd` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode nd) {
not nd.isHidden() or
not nd.(MidPathNode).isHidden() or
nd instanceof SourcePathNode or
nd instanceof SinkPathNode
}