Skip to content

Commit 04fbb8c

Browse files
committed
JS: Do alias analysis is CG construction
1 parent 69563a7 commit 04fbb8c

File tree

1 file changed

+72
-6
lines changed

1 file changed

+72
-6
lines changed

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

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,86 @@
55
private import javascript
66
private import semmle.javascript.dataflow.internal.StepSummary
77
private import semmle.javascript.dataflow.internal.PreCallGraphStep
8+
private import semmle.javascript.dataflow.internal.FlowSteps
89
private import semmle.javascript.internal.NameResolution
910

1011
cached
1112
module CallGraph {
13+
pragma[nomagic]
14+
private predicate shouldBackTrack(DataFlow::SourceNode node) {
15+
exists(DataFlow::Node rhs | rhs = node.getAPropertyWrite().getRhs().getALocalSource() |
16+
track(_) = rhs
17+
)
18+
}
19+
20+
pragma[nomagic]
21+
private DataFlow::SourceNode backtrackStoreTarget() {
22+
shouldBackTrack(result)
23+
or
24+
AccessPath::step(result.getALocalUse(), backtrackStoreTarget())
25+
or
26+
propertyFlowStep(result.getALocalUse(), backtrackStoreTarget())
27+
or
28+
storeReadStep(result, backtrackStoreTarget())
29+
}
30+
31+
pragma[nomagic]
32+
private predicate shouldTrack(DataFlow::SourceNode node) {
33+
node instanceof DataFlow::FunctionNode
34+
or
35+
node instanceof DataFlow::ClassNode
36+
or
37+
(
38+
node instanceof DataFlow::ObjectLiteralNode or
39+
node instanceof DataFlow::InvokeNode or
40+
node instanceof DataFlow::ArrayLiteralNode
41+
) and
42+
backtrackStoreTarget() = node
43+
}
44+
45+
pragma[nomagic]
46+
private predicate deepStore(DataFlow::SourceNode node1, string prop, DataFlow::SourceNode node2) {
47+
track(node2).getAPropertyWrite(prop).getRhs().getALocalSource() = node1
48+
}
49+
50+
pragma[nomagic]
51+
private predicate deepRead(DataFlow::SourceNode node1, string prop, DataFlow::SourceNode node2) {
52+
track(node1).getAPropertyRead(prop) = node2
53+
}
54+
55+
pragma[nomagic]
56+
private predicate storeReadStep(DataFlow::SourceNode node1, DataFlow::SourceNode node2) {
57+
exists(DataFlow::SourceNode base, string name |
58+
deepStore(node1, name, base) and
59+
deepRead(base, name, node2)
60+
)
61+
}
62+
63+
pragma[nomagic]
64+
private DataFlow::SourceNode track(DataFlow::SourceNode source) {
65+
shouldTrack(source) and
66+
(
67+
result = source
68+
or
69+
AccessPath::step(track(source).getALocalUse(), result)
70+
or
71+
propertyFlowStep(track(source).getALocalUse(), result)
72+
or
73+
storeReadStep(track(source), result)
74+
)
75+
}
76+
1277
/** Gets the function referenced by `node`, as determined by the type inference. */
1378
cached
1479
Function getAFunctionValue(AnalyzedNode node) {
15-
result = node.getAValue().(AbstractCallable).getFunction()
16-
or
17-
node = NameResolution::trackFunctionValue(result).toDataFlowNodeOut()
80+
exists(DataFlow::FunctionNode func |
81+
result = func.getFunction() and
82+
track(func).getALocalUse() = node
83+
)
1884
or
19-
exists(DataFlow::Node pred |
20-
AccessPath::step(pred, node) and
21-
result = getAFunctionValue(pred)
85+
exists(DataFlow::ClassNode cls |
86+
result = cls.getConstructor().getFunction() and
87+
track(cls).getALocalUse() = node
2288
)
2389
}
2490

0 commit comments

Comments
 (0)