Skip to content

Commit 86e646b

Browse files
authored
Merge pull request #975 from asger-semmle/global-closure-dataflow
Approved by esben-semmle
2 parents 9d78779 + f9111f6 commit 86e646b

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

javascript/ql/src/semmle/javascript/dataflow/TypeInference.qll

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ class AnalyzedNode extends DataFlow::Node {
4747
*/
4848
AnalyzedNode localFlowPred() { result = getAPredecessor() }
4949

50+
/**
51+
* INTERNAL. Do not use.
52+
*
53+
* Gets another data flow node whose value flows into this node in a global step
54+
* (this is, involving global variables).
55+
*/
56+
AnalyzedNode globalFlowPred() { none() }
57+
5058
/**
5159
* Gets an abstract value that this node may evaluate to at runtime.
5260
*
@@ -57,7 +65,9 @@ class AnalyzedNode extends DataFlow::Node {
5765
* instances is also performed.
5866
*/
5967
cached
60-
AbstractValue getAValue() { result = getALocalValue() }
68+
AbstractValue getAValue() {
69+
result = getALocalValue()
70+
}
6171

6272
/**
6373
* INTERNAL: Do not use.
@@ -68,7 +78,7 @@ class AnalyzedNode extends DataFlow::Node {
6878
* and global), IIFEs, ES6-style imports that can be resolved uniquely, and
6979
* the properties of CommonJS `module` and `exports` objects. No
7080
* tracking through the properties of object literals and function/class
71-
* instances is performed.
81+
* instances is performed, other than those accounted for by `globalFlowPred`.
7282
*/
7383
cached
7484
AbstractValue getALocalValue() {
@@ -82,6 +92,9 @@ class AnalyzedNode extends DataFlow::Node {
8292
exists(DataFlow::Incompleteness cause |
8393
isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
8494
)
95+
or
96+
result = globalFlowPred().getALocalValue() and
97+
shouldTrackGlobally(result)
8598
}
8699

87100
/** Gets a type inferred for this node. */
@@ -282,3 +295,8 @@ private class AnalyzedAsyncFunction extends AnalyzedFunction {
282295

283296
override AbstractValue getAReturnValue() { result = TAbstractOtherObject() }
284297
}
298+
299+
/**
300+
* Holds if the given value should be propagated along `globalFlowPred()` edges.
301+
*/
302+
private predicate shouldTrackGlobally(AbstractValue value) { value instanceof AbstractCallable }

javascript/ql/src/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,11 @@ private class AnalyzedClosureGlobalAccessPath extends AnalyzedNode, AnalyzedProp
381381
accessPath = Closure::getClosureNamespaceFromSourceNode(this)
382382
}
383383

384-
override AnalyzedNode localFlowPred() {
384+
override AnalyzedNode globalFlowPred() {
385385
exists(DataFlow::PropWrite write |
386386
Closure::getWrittenClosureNamespace(write) = accessPath and
387387
result = write.getRhs()
388388
)
389-
or
390-
result = AnalyzedNode.super.localFlowPred()
391389
}
392390

393391
override predicate reads(AbstractValue base, string propName) {

0 commit comments

Comments
 (0)