JS: support flow out of "this" in constructor call

This commit is contained in:
Asger F
2019-01-11 12:50:59 +00:00
parent 370a9e491c
commit 6d1eab8a4b
5 changed files with 63 additions and 5 deletions

View File

@@ -606,11 +606,16 @@ private predicate storeStep(
basicStoreStep(pred, succ, prop) and
summary = PathSummary::level()
or
exists(Function f, DataFlow::Node mid, DataFlow::Node base |
exists(Function f, DataFlow::Node mid |
// `f` stores its parameter `pred` in property `prop` of a value that it returns,
// and `succ` is an invocation of `f`
reachableFromInput(f, succ, pred, mid, cfg, summary) and
returnedPropWrite(f, base, prop, mid)
(
returnedPropWrite(f, _, prop, mid)
or
succ instanceof DataFlow::NewNode and
receiverPropWrite(f, prop, mid)
)
)
}
@@ -622,6 +627,13 @@ predicate returnedPropWrite(Function f, DataFlow::SourceNode base, string prop,
base.flowsToExpr(f.getAReturnedExpr())
}
/**
* Holds if `f` may return `base`, which has a write of property `prop` with right-hand side `rhs`.
*/
predicate receiverPropWrite(Function f, string prop, DataFlow::Node rhs) {
DataFlow::thisNode(f).hasPropertyWrite(prop, rhs)
}
/**
* Holds if `rhs` is the right-hand side of a write to property `prop`, and `nd` is reachable
* from the base of that write under configuration `cfg` (possibly through callees) along a

View File

@@ -802,6 +802,13 @@ module DataFlow {
*/
predicate thisNode(DataFlow::Node node, StmtContainer container) { node = TThisNode(container) }
/**
* Gets the node representing the receiver of the given function, or `this` in the given top-level.
*
* Has no result if `container` is an arrow function.
*/
DataFlow::ThisNode thisNode(StmtContainer container) { result = TThisNode(container) }
/**
* A classification of flows that are not modeled, or only modeled incompletely, by
* `DataFlowNode`:

View File

@@ -118,9 +118,11 @@ predicate callStep(DataFlow::Node pred, DataFlow::Node succ) {
* from a function call.
*/
predicate returnStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Function f |
returnExpr(f, pred, _) and
calls(succ, f)
exists(Function f | calls(succ, f) |
returnExpr(f, pred, _)
or
succ instanceof DataFlow::NewNode and
DataFlow::thisNode(pred, f)
)
}