mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
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:
@@ -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() }
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user