Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions javascript/ql/lib/semmle/javascript/ApiGraphs.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,9 @@ module API {
exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev |
prev = trackUseNode(nd, promisified, boundArgs, prop, t) and
StepSummary::step(prev, res, summary) and
result = t.append(summary)
result = t.append(summary) and
// Block argument-passing into 'this' when it determines the call target
not summary = CallReceiverStep()
)
}

Expand Down Expand Up @@ -1381,7 +1383,9 @@ module API {
exists(DataFlow::TypeBackTracker t, StepSummary summary, DataFlow::Node next |
next = trackDefNode(nd, t) and
StepSummary::step(prev, next, summary) and
result = t.prepend(summary)
result = t.prepend(summary) and
// Block argument-passing steps from 'this' back to a receiver when it determines the call target
not summary = CallReceiverStep()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class TypeTracker extends TTypeTracker {
or
step = CallStep() and result = MkTypeTracker(true, prop)
or
step = CallReceiverStep() and result = MkTypeTracker(true, prop)
or
step = ReturnStep() and hasCall = false and result = this
or
step = LoadStep(prop) and result = MkTypeTracker(hasCall, "")
Expand Down Expand Up @@ -238,6 +240,8 @@ class TypeBackTracker extends TTypeBackTracker {
or
step = CallStep() and hasReturn = false and result = this
or
step = CallReceiverStep() and hasReturn = false and result = this
or
step = ReturnStep() and result = MkTypeBackTracker(true, prop)
or
exists(string p | step = LoadStep(p) and prop = "" and result = MkTypeBackTracker(hasReturn, p))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ private module Cached {
newtype TStepSummary =
LevelStep() or
CallStep() or
CallReceiverStep() or
ReturnStep() or
StoreStep(PropertyName prop) or
LoadStep(PropertyName prop) or
Expand Down Expand Up @@ -101,6 +102,15 @@ private module Cached {
)
}

pragma[nomagic]
private predicate isReceiverForMethodDispatch(DataFlow::Node node) {
exists(DataFlow::SourceNode base, DataFlow::CallNode invoke |
node = invoke.getReceiver() and
base = node.getALocalSource() and
invoke.getCalleeNode() = base.getAPropertyRead()
)
}

/**
* INTERNAL: Use `TypeBackTracker.smallstep()` instead.
*/
Expand All @@ -116,7 +126,11 @@ private module Cached {
or
// Flow into function
callStep(pred, succ) and
summary = CallStep()
(
if isReceiverForMethodDispatch(pred)
then summary = CallReceiverStep()
else summary = CallStep()
)
or
// Flow out of function
returnStep(pred, succ) and
Expand Down Expand Up @@ -251,6 +265,8 @@ class StepSummary extends TStepSummary {
or
this instanceof CallStep and result = "call"
or
this instanceof CallReceiverStep and result = "call-receiver"
or
this instanceof ReturnStep and result = "return"
or
exists(string prop | this = StoreStep(prop) | result = "store " + prop)
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import ApiGraphs.VerifyAssertions
6 changes: 6 additions & 0 deletions javascript/ql/test/ApiGraphs/explicit-this/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "explicit-this",
"dependencies": {
"something": "*"
}
}
7 changes: 7 additions & 0 deletions javascript/ql/test/ApiGraphs/explicit-this/tst.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const lib = require('something');

function f() {
this.two(); /** use=moduleImport("something").getMember("exports").getMember("one").getMember("two").getReturn() */
}

f.call(lib.one);
Loading