JS: Add AdditionalFlowInternal

This provides access to more features than we want to expose publicly at the moment, but is useful for modelling certain language features.
This commit is contained in:
Asger F
2023-10-10 10:42:58 +02:00
parent 3f20d71a9b
commit 46fec8ea7e
3 changed files with 68 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
private import javascript
private import semmle.javascript.dataflow.internal.DataFlowNode
private import semmle.javascript.dataflow.internal.DataFlowPrivate
/**
* Gets a data-flow node synthesized using `AdditionalFlowInternal#needsSynthesizedNode`.
*/
DataFlow::Node getSynthesizedNode(AstNode node, string tag) {
result = TGenericSynthesizedNode(node, tag, _)
}
/**
* An extension to `AdditionalFlowStep` with additional internal-only predicates.
*/
class AdditionalFlowInternal extends DataFlow::AdditionalFlowStep {
/**
* Holds if a data-flow node should be synthesized for the pair `(node, tag)`.
*
* The node can be obtained using `getSynthesizedNode(node, tag)`.
*
* `container` will be seen as the node's enclosing container.
*/
predicate needsSynthesizedNode(AstNode node, string tag, DataFlowCallable container) { none() }
/**
* Holds if `node` should only permit flow of values stored in `contents`.
*/
predicate expectsContent(DataFlow::Node node, DataFlow::ContentSet contents) { none() }
/**
* Holds if `node` should not permit flow of values stored in `contents`.
*/
predicate clearsContent(DataFlow::Node node, DataFlow::ContentSet contents) { none() }
}

View File

@@ -5,6 +5,8 @@
*/
private import javascript
private import semmle.javascript.dataflow.internal.AdditionalFlowInternal
private import semmle.javascript.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import semmle.javascript.dataflow.internal.sharedlib.FlowSummaryImpl as FlowSummaryImpl
cached
private module Cached {
@@ -53,6 +55,9 @@ private module Cached {
TFlowSummaryIntermediateAwaitStoreNode(FlowSummaryImpl::Private::SummaryNode sn) {
FlowSummaryImpl::Private::Steps::summaryStoreStep(sn, MkAwaited(), _)
} or
TGenericSynthesizedNode(AstNode node, string tag, DataFlowPrivate::DataFlowCallable container) {
any(AdditionalFlowInternal flow).needsSynthesizedNode(node, tag, container)
}
}
import Cached

View File

@@ -2,6 +2,7 @@ private import javascript
private import semmle.javascript.dataflow.internal.CallGraphs
private import semmle.javascript.dataflow.internal.DataFlowNode
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
private import semmle.javascript.dataflow.internal.AdditionalFlowInternal
private import semmle.javascript.dataflow.internal.Contents::Private
private import semmle.javascript.dataflow.internal.VariableCapture
private import semmle.javascript.dataflow.internal.sharedlib.DataFlowImplCommon as DataFlowImplCommon
@@ -40,6 +41,26 @@ class FlowSummaryIntermediateAwaitStoreNode extends DataFlow::Node,
}
}
class GenericSynthesizedNode extends DataFlow::Node, TGenericSynthesizedNode {
private AstNode node;
private string tag;
private DataFlowCallable container;
GenericSynthesizedNode() { this = TGenericSynthesizedNode(node, tag, container) }
override StmtContainer getContainer() { result = container.asSourceCallable() }
override string toString() { result = "[synthetic node] " + tag }
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
node.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
string getTag() { result = tag }
}
cached
newtype TReturnKind =
MkNormalReturnKind() or
@@ -235,6 +256,8 @@ DataFlowCallable nodeGetEnclosingCallable(Node node) {
result.asLibraryCallable() = node.(FlowSummaryNode).getSummarizedCallable()
or
result.asLibraryCallable() = node.(FlowSummaryIntermediateAwaitStoreNode).getSummarizedCallable()
or
node = TGenericSynthesizedNode(_, _, result)
}
private newtype TDataFlowType =
@@ -255,6 +278,8 @@ predicate nodeIsHidden(Node node) {
node instanceof FlowSummaryNode
or
node instanceof FlowSummaryIntermediateAwaitStoreNode
or
node instanceof GenericSynthesizedNode
}
predicate neverSkipInPathGraph(Node node) {
@@ -694,6 +719,8 @@ predicate clearsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryReadStep(_, MkAwaited(),
n.(FlowSummaryNode).getSummaryNode()) and
c = MkPromiseFilter()
or
any(AdditionalFlowInternal flow).clearsContent(n, c)
}
/**
@@ -708,6 +735,8 @@ predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryStoreStep(_, MkAwaited(),
n.(FlowSummaryNode).getSummaryNode()) and
c = MkPromiseFilter()
or
any(AdditionalFlowInternal flow).expectsContent(n, c)
}
/**