JavaScript: Add libraries for forward and backward data-flow exploration.

This commit is contained in:
Max Schaefer
2019-10-22 09:32:51 +01:00
parent 2a3980222b
commit 03c9a40ba3
2 changed files with 86 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
/**
* Provides machinery for performing backward data-flow exploration.
*
* Importing this module effectively makes all data-flow and taint-tracking configurations
* ignore their `isSource` predicate. Instead, flow is tracked from any _initial node_ (that is,
* a node without incoming flow) to a sink node. All initial nodes are then treated as source
* nodes.
*
* Data-flow exploration cannot be used with configurations depending on other configurations.
*
* NOTE: This library should only be used for debugging, not in production code. Backward
* exploration in particular does not scale on non-trivial code bases and hence is of limited
* usefulness as it stands.
*/
import javascript
private class BackwardExploringConfiguration extends DataFlow::Configuration {
DataFlow::Configuration cfg;
BackwardExploringConfiguration() {
this = cfg
}
override predicate isSource(DataFlow::Node node) { any() }
override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) |
source = src.getNode() and
sink = snk.getNode()
)
}
override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) {
exists(DataFlow::MidPathNode first |
source.getConfiguration() = this and
source.getASuccessor() = first and
not exists(DataFlow::MidPathNode mid | mid.getASuccessor() = first) and
first.getASuccessor*() = sink
)
}
}

View File

@@ -0,0 +1,42 @@
/**
* Provides machinery for performing forward data-flow exploration.
*
* Importing this module effectively makes all data-flow and taint-tracking configurations
* ignore their `isSink` predicate. Instead, flow is tracked from source nodes as far as
* possible, until a _terminal node_ (that is, a node without any outgoing flow) is reached.
* All terminal nodes are then treated as sink nodes.
*
* Data-flow exploration cannot be used with configurations depending on other configurations.
*
* NOTE: This library should only be used for debugging, not in production code.
*/
import javascript
private class ForwardExploringConfiguration extends DataFlow::Configuration {
DataFlow::Configuration cfg;
ForwardExploringConfiguration() {
this = cfg
}
override predicate isSink(DataFlow::Node node) { any() }
override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) |
source = src.getNode() and
sink = snk.getNode()
)
}
override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) {
exists(DataFlow::MidPathNode last |
source.getConfiguration() = this and
source.getASuccessor*() = last and
not last.getASuccessor() instanceof DataFlow::MidPathNode and
last.getASuccessor() = sink
)
}
}