JS: Add implied receiver steps

This commit is contained in:
Asger F
2023-04-13 10:52:11 +02:00
parent 74dbc71535
commit 869c6d27fe
3 changed files with 34 additions and 4 deletions

View File

@@ -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()

View File

@@ -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()
)
}
}

View File

@@ -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)