mirror of
https://github.com/github/codeql.git
synced 2026-04-25 08:45:14 +02:00
JS: Cache some SourceNode getter methods differently
This commit is contained in:
@@ -39,7 +39,7 @@ class SourceNode extends DataFlow::Node {
|
||||
* Holds if this node flows into `sink` in zero or more local (that is,
|
||||
* intra-procedural) steps.
|
||||
*/
|
||||
predicate flowsTo(DataFlow::Node sink) { hasLocalSource(sink, this) }
|
||||
predicate flowsTo(DataFlow::Node sink) { Cached::hasLocalSource(sink, this) }
|
||||
|
||||
/**
|
||||
* Holds if this node flows into `sink` in zero or more local (that is,
|
||||
@@ -51,8 +51,7 @@ class SourceNode extends DataFlow::Node {
|
||||
* Gets a reference (read or write) of property `propName` on this node.
|
||||
*/
|
||||
DataFlow::PropRef getAPropertyReference(string propName) {
|
||||
result = getAPropertyReference() and
|
||||
result.getPropertyName() = propName
|
||||
Cached::namedPropRef(this, propName, result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +77,11 @@ class SourceNode extends DataFlow::Node {
|
||||
/**
|
||||
* Gets a reference (read or write) of any property on this node.
|
||||
*/
|
||||
DataFlow::PropRef getAPropertyReference() { flowsTo(result.getBase()) }
|
||||
DataFlow::PropRef getAPropertyReference() {
|
||||
Cached::namedPropRef(this, _, result)
|
||||
or
|
||||
Cached::dynamicPropRef(this, result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a read of any property on this node.
|
||||
@@ -113,11 +116,8 @@ class SourceNode extends DataFlow::Node {
|
||||
* that is, `o.m(...)` or `o[p](...)`.
|
||||
*/
|
||||
DataFlow::CallNode getAMethodCall(string methodName) {
|
||||
exists(PropAccess pacc |
|
||||
pacc = result.getCalleeNode().asExpr().getUnderlyingReference() and
|
||||
flowsToExpr(pacc.getBase()) and
|
||||
pacc.getPropertyName() = methodName
|
||||
)
|
||||
result = getAMemberInvocation(methodName) and
|
||||
Cached::isSyntacticMethodCall(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +148,7 @@ class SourceNode extends DataFlow::Node {
|
||||
/**
|
||||
* Gets an invocation (with our without `new`) of this node.
|
||||
*/
|
||||
DataFlow::InvokeNode getAnInvocation() { flowsTo(result.getCalleeNode()) }
|
||||
DataFlow::InvokeNode getAnInvocation() { Cached::invocation(this, result) }
|
||||
|
||||
/**
|
||||
* Gets a function call to this node.
|
||||
@@ -192,21 +192,61 @@ class SourceNode extends DataFlow::Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `source` is a `SourceNode` that can reach `sink` via local flow steps.
|
||||
*
|
||||
* The slightly backwards parametering ordering is to force correct indexing.
|
||||
* Cached predicates used by the member predicates in `SourceNode`.
|
||||
*/
|
||||
cached
|
||||
private predicate hasLocalSource(DataFlow::Node sink, DataFlow::Node source) {
|
||||
// Declaring `source` to be a `SourceNode` currently causes a redundant check in the
|
||||
// recursive case, so instead we check it explicitly here.
|
||||
source = sink and
|
||||
source instanceof DataFlow::SourceNode
|
||||
or
|
||||
exists(DataFlow::Node mid |
|
||||
hasLocalSource(mid, source) and
|
||||
DataFlow::localFlowStep(mid, sink)
|
||||
)
|
||||
private module Cached {
|
||||
/**
|
||||
* Holds if `source` is a `SourceNode` that can reach `sink` via local flow steps.
|
||||
*
|
||||
* The slightly backwards parametering ordering is to force correct indexing.
|
||||
*/
|
||||
cached
|
||||
predicate hasLocalSource(DataFlow::Node sink, DataFlow::Node source) {
|
||||
// Declaring `source` to be a `SourceNode` currently causes a redundant check in the
|
||||
// recursive case, so instead we check it explicitly here.
|
||||
source = sink and
|
||||
source instanceof DataFlow::SourceNode
|
||||
or
|
||||
exists(DataFlow::Node mid |
|
||||
hasLocalSource(mid, source) and
|
||||
DataFlow::localFlowStep(mid, sink)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `base` flows to the base of `ref` and `ref` has property name `prop`.
|
||||
*/
|
||||
cached
|
||||
predicate namedPropRef(DataFlow::SourceNode base, string prop, DataFlow::PropRef ref) {
|
||||
hasLocalSource(ref.getBase(), base) and
|
||||
ref.getPropertyName() = prop
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `base` flows to the base of `ref` and `ref` has no known property name.
|
||||
*/
|
||||
cached
|
||||
predicate dynamicPropRef(DataFlow::SourceNode base, DataFlow::PropRef ref) {
|
||||
hasLocalSource(ref.getBase(), base) and
|
||||
not exists(ref.getPropertyName())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `func` flows to the callee of `invoke`.
|
||||
*/
|
||||
cached
|
||||
predicate invocation(DataFlow::SourceNode func, DataFlow::InvokeNode invoke) {
|
||||
hasLocalSource(invoke.getCalleeNode(), func)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `invoke` has the syntactic shape of a method call.
|
||||
*/
|
||||
cached
|
||||
predicate isSyntacticMethodCall(DataFlow::CallNode call) {
|
||||
call.asExpr().(CallExpr).getCallee().getUnderlyingReference() instanceof PropAccess
|
||||
}
|
||||
}
|
||||
|
||||
module SourceNode {
|
||||
|
||||
Reference in New Issue
Block a user