Skip to content

Commit 587ad5c

Browse files
committed
JS: Refine criteria so that explicit this-passing is not affected
1 parent 4d33190 commit 587ad5c

File tree

4 files changed

+25
-6
lines changed

4 files changed

+25
-6
lines changed

javascript/ql/lib/semmle/javascript/ApiGraphs.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,8 +1325,8 @@ module API {
13251325
prev = trackUseNode(nd, promisified, boundArgs, prop, t) and
13261326
StepSummary::step(prev, res, summary) and
13271327
result = t.append(summary) and
1328-
// Block argument-passing into 'this'
1329-
not (summary = CallStep() and res instanceof DataFlow::ThisNode)
1328+
// Block argument-passing into 'this' when it determines the call target
1329+
not summary = CallReceiverStep()
13301330
)
13311331
}
13321332

@@ -1384,8 +1384,8 @@ module API {
13841384
next = trackDefNode(nd, t) and
13851385
StepSummary::step(prev, next, summary) and
13861386
result = t.prepend(summary) and
1387-
// Block argument-passing steps from 'this' back to a receiver
1388-
not (summary = CallStep() and prev instanceof DataFlow::ThisNode)
1387+
// Block argument-passing steps from 'this' back to a receiver when it determines the call target
1388+
not summary = CallReceiverStep()
13891389
)
13901390
}
13911391

javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class TypeTracker extends TTypeTracker {
6565
or
6666
step = CallStep() and result = MkTypeTracker(true, prop)
6767
or
68+
step = CallReceiverStep() and result = MkTypeTracker(true, prop)
69+
or
6870
step = ReturnStep() and hasCall = false and result = this
6971
or
7072
step = LoadStep(prop) and result = MkTypeTracker(hasCall, "")
@@ -238,6 +240,8 @@ class TypeBackTracker extends TTypeBackTracker {
238240
or
239241
step = CallStep() and hasReturn = false and result = this
240242
or
243+
step = CallReceiverStep() and hasReturn = false and result = this
244+
or
241245
step = ReturnStep() and result = MkTypeBackTracker(true, prop)
242246
or
243247
exists(string p | step = LoadStep(p) and prop = "" and result = MkTypeBackTracker(hasReturn, p))

javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ private module Cached {
4343
newtype TStepSummary =
4444
LevelStep() or
4545
CallStep() or
46+
CallReceiverStep() or
4647
ReturnStep() or
4748
StoreStep(PropertyName prop) or
4849
LoadStep(PropertyName prop) or
@@ -101,6 +102,15 @@ private module Cached {
101102
)
102103
}
103104

105+
pragma[nomagic]
106+
private predicate isReceiverForMethodDispatch(DataFlow::Node node) {
107+
exists(DataFlow::SourceNode base, DataFlow::CallNode invoke |
108+
node = invoke.getReceiver() and
109+
base = node.getALocalSource() and
110+
invoke.getCalleeNode() = base.getAPropertyRead()
111+
)
112+
}
113+
104114
/**
105115
* INTERNAL: Use `TypeBackTracker.smallstep()` instead.
106116
*/
@@ -116,7 +126,11 @@ private module Cached {
116126
or
117127
// Flow into function
118128
callStep(pred, succ) and
119-
summary = CallStep()
129+
(
130+
if isReceiverForMethodDispatch(pred)
131+
then summary = CallReceiverStep()
132+
else summary = CallStep()
133+
)
120134
or
121135
// Flow out of function
122136
returnStep(pred, succ) and
@@ -251,6 +265,8 @@ class StepSummary extends TStepSummary {
251265
or
252266
this instanceof CallStep and result = "call"
253267
or
268+
this instanceof CallReceiverStep and result = "call-receiver"
269+
or
254270
this instanceof ReturnStep and result = "return"
255271
or
256272
exists(string prop | this = StoreStep(prop) | result = "store " + prop)
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
| tst.js:4:17:4:119 | /** use ... rn() */ | use moduleImport("something").getMember("exports").getMember("one") has no outgoing edge labelled getMember("two"); it has no outgoing edges at all. |

0 commit comments

Comments
 (0)