mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
JS: Add implied receiver steps
This commit is contained in:
@@ -806,6 +806,10 @@ private predicate basicFlowStepNoBarrier(
|
||||
callStep(pred, succ) and
|
||||
summary = PathSummary::call()
|
||||
or
|
||||
// Implied receiver flow
|
||||
CallGraph::impliedReceiverStep(pred, succ) and
|
||||
summary = PathSummary::call()
|
||||
or
|
||||
// Flow out of function
|
||||
returnStep(pred, succ) and
|
||||
summary = PathSummary::return()
|
||||
|
||||
@@ -241,22 +241,26 @@ module CallGraph {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate shouldTrackObjectWithMethods(DataFlow::SourceNode node) {
|
||||
private DataFlow::FunctionNode getAMethodOnPlainObject(DataFlow::SourceNode node) {
|
||||
(
|
||||
(
|
||||
node instanceof DataFlow::ObjectLiteralNode
|
||||
or
|
||||
node instanceof DataFlow::FunctionNode
|
||||
) and
|
||||
node.getAPropertySource() instanceof DataFlow::FunctionNode
|
||||
result = node.getAPropertySource()
|
||||
or
|
||||
exists(node.(DataFlow::ObjectLiteralNode).getPropertyGetter(_))
|
||||
result = node.(DataFlow::ObjectLiteralNode).getPropertyGetter(_)
|
||||
or
|
||||
exists(node.(DataFlow::ObjectLiteralNode).getPropertySetter(_))
|
||||
result = node.(DataFlow::ObjectLiteralNode).getPropertySetter(_)
|
||||
) and
|
||||
not node.getTopLevel().isExterns()
|
||||
}
|
||||
|
||||
private predicate shouldTrackObjectWithMethods(DataFlow::SourceNode node) {
|
||||
exists(getAMethodOnPlainObject(node))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a step summary for tracking object literals.
|
||||
*
|
||||
@@ -273,4 +277,22 @@ module CallGraph {
|
||||
or
|
||||
StepSummary::step(getAnAllocationSiteRef(node), result, objectWithMethodsStep())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `pred` is assumed to flow to `succ` because a method is stored on an object that is assumed
|
||||
* to be the receiver of calls to that method.
|
||||
*
|
||||
* For example, object literal below is assumed to flow to the receiver of the `foo` function:
|
||||
* ```js
|
||||
* let obj = {};
|
||||
* obj.foo = function() {}
|
||||
* ```
|
||||
*/
|
||||
cached
|
||||
predicate impliedReceiverStep(DataFlow::SourceNode pred, DataFlow::SourceNode succ) {
|
||||
exists(DataFlow::SourceNode host |
|
||||
pred = getAnAllocationSiteRef(host) and
|
||||
succ = getAMethodOnPlainObject(host).getReceiver()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,10 @@ private module Cached {
|
||||
DataFlow::localFieldStep(pred, succ) and
|
||||
summary = LevelStep()
|
||||
or
|
||||
// Implied flow of host object into 'this' of a method
|
||||
CallGraph::impliedReceiverStep(pred, succ) and
|
||||
summary = CallStep()
|
||||
or
|
||||
exists(string prop |
|
||||
basicStoreStep(pred, succ, prop) and
|
||||
summary = StoreStep(prop)
|
||||
|
||||
Reference in New Issue
Block a user