Skip to content

Commit 331c2a9

Browse files
committed
wp
1 parent 613895e commit 331c2a9

1 file changed

Lines changed: 220 additions & 0 deletions

File tree

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
private import javascript
2+
private import semmle.javascript.dataflow.internal.StepSummary
3+
4+
private newtype TLabel =
5+
MkMemberLabel(PropertyName prop) or
6+
MkArgumentLabel(int n) { exists(any(DataFlow::InvokeNode i).getArgument(n)) } or
7+
MkParameterLabel(int n) { exists(any(DataFlow::FunctionNode i).getParameter(n)) }
8+
9+
class Label extends TLabel {
10+
string asMember() { this = MkMemberLabel(result) }
11+
12+
int asArgumentIndex() { this = MkArgumentLabel(result) }
13+
14+
int asParameterIndex() { this = MkParameterLabel(result) }
15+
16+
string toString() {
17+
result = "Member[" + this.asMember() + "]" or
18+
result = "Argument[" + this.asArgumentIndex() + "]" or
19+
result = "Parameter[" + this.asParameterIndex() + "]"
20+
}
21+
}
22+
23+
module API {
24+
private class Node = DataFlow::Node;
25+
26+
predicate useToUseStep(Node node1, Label label, Node node2) {
27+
exists(DataFlow::PropRead read |
28+
node1 = read.getBase() and
29+
node2 = read and
30+
label.asMember() = read.getPropertyName()
31+
)
32+
}
33+
34+
predicate defToDefStep(Node node1, Label label, Node node2) {
35+
exists(DataFlow::PropWrite write |
36+
node1 = write.getBase().getALocalSource() and
37+
node2 = write.getRhs() and
38+
label.asMember() = write.getPropertyName()
39+
)
40+
}
41+
42+
predicate defToUseStep(Node node1, Label label, Node node2) {
43+
exists(DataFlow::FunctionNode fun, int i |
44+
node1 = fun and
45+
node2 = fun.getParameter(i) and
46+
label.asParameterIndex() = i
47+
)
48+
}
49+
50+
predicate useToDefStep(Node node1, Label label, Node node2) {
51+
exists(DataFlow::InvokeNode node, int i |
52+
node1 = node.getCalleeNode() and
53+
node2 = node.getArgument(i) and
54+
label.asArgumentIndex() = i
55+
)
56+
}
57+
58+
signature module DeepFlowInputSig {
59+
predicate isEntryPointUse(Node node);
60+
61+
predicate isEntryPointDef(Node node);
62+
63+
bindingset[node]
64+
predicate shouldInclude(Node node);
65+
}
66+
67+
overlay[local?]
68+
module DeepFlow<DeepFlowInputSig S> {
69+
private import S
70+
71+
private predicate isUseNodeRoot(DataFlow::SourceNode node) {
72+
isEntryPointUse(node)
73+
or
74+
useToUseStep(trackUse(_), _, node) and shouldInclude(node)
75+
or
76+
defToUseStep(trackDef(_), _, node) and shouldInclude(node)
77+
}
78+
79+
DataFlow::SourceNode trackUse(DataFlow::SourceNode node, DataFlow::TypeTracker t) {
80+
isUseNodeRoot(node) and
81+
result = node and
82+
t.start()
83+
or
84+
exists(DataFlow::TypeTracker t2 | result = trackUse(node, t2).track(t2, t))
85+
}
86+
87+
DataFlow::SourceNode trackUse(DataFlow::SourceNode node) {
88+
result = trackUse(node, DataFlow::TypeTracker::end())
89+
}
90+
91+
private predicate isDefNodeRoot(DataFlow::Node node) {
92+
isEntryPointDef(node)
93+
or
94+
useToDefStep(trackUse(_), _, node) and shouldInclude(node)
95+
or
96+
defToDefStep(trackDef(_), _, node) and shouldInclude(node)
97+
}
98+
99+
DataFlow::SourceNode trackDef(DataFlow::Node node, DataFlow::TypeBackTracker t) {
100+
isDefNodeRoot(node) and
101+
result = node.getALocalSource() and
102+
t.start()
103+
or
104+
exists(DataFlow::TypeBackTracker t2 | result = trackDef(node, t2).backtrack(t2, t))
105+
}
106+
107+
DataFlow::SourceNode trackDef(DataFlow::Node node) {
108+
result = trackDef(node, DataFlow::TypeBackTracker::end())
109+
}
110+
}
111+
112+
private module Input1 implements DeepFlowInputSig {
113+
predicate isEntryPointUse(Node node) {
114+
exists(Import imprt |
115+
imprt.getImportedPathString().regexpMatch("[^./].*") and
116+
node = imprt.getImportedModuleNode()
117+
)
118+
}
119+
120+
predicate isEntryPointDef(Node node) {
121+
exists(PackageJson pkg |
122+
not pkg.isPrivate() and
123+
node =
124+
[pkg.getMainModule().getAnExportedValue(_), pkg.getMainModule().getABulkExportedNode()]
125+
)
126+
}
127+
128+
bindingset[node]
129+
predicate shouldInclude(Node node) { any() }
130+
}
131+
132+
private module DeepFlow1 = DeepFlow<Input1>;
133+
134+
overlay[local]
135+
DataFlow::SourceNode trackUseLocal(DataFlow::SourceNode node) =
136+
forceLocal(DeepFlow1::trackUse/1)(node, result)
137+
138+
overlay[local]
139+
DataFlow::SourceNode trackDefLocal(DataFlow::Node node) =
140+
forceLocal(DeepFlow1::trackDef/1)(node, result)
141+
142+
bindingset[node]
143+
overlay[global]
144+
pragma[inline_late]
145+
private predicate isInOverlayChangedFile(DataFlow::Node node) {
146+
overlayChangedFiles(node.getFile().getAbsolutePath())
147+
}
148+
149+
predicate stepIntoOverlay(Node node1, Node node2, StepSummary summary) {
150+
StepSummary::smallstep(node1, node2, summary) and
151+
not isInOverlayChangedFile(node1) and
152+
isInOverlayChangedFile(node2)
153+
}
154+
155+
predicate stepOutOfOverlay(Node node1, Node node2, StepSummary summary) {
156+
StepSummary::smallstep(node1, node2, summary) and
157+
isInOverlayChangedFile(node1) and
158+
not isInOverlayChangedFile(node2)
159+
}
160+
161+
private module Input2 implements DeepFlowInputSig {
162+
predicate isEntryPointUse(Node node) {
163+
stepIntoOverlay(trackUseLocal(node).getALocalUse(), _, _)
164+
}
165+
166+
predicate isEntryPointDef(Node node) { stepOutOfOverlay(_, trackDefLocal(node), _) }
167+
168+
predicate shouldInclude(Node node) { isInOverlayChangedFile(node) }
169+
}
170+
171+
private module DeepFlow2 = DeepFlow<Input2>;
172+
173+
DataFlow::SourceNode trackUseFinal(DataFlow::SourceNode node) {
174+
result = DeepFlow1::trackUse(node)
175+
or
176+
result = DeepFlow2::trackUse(node)
177+
}
178+
179+
DataFlow::SourceNode trackDefFinal(DataFlow::Node node) {
180+
result = DeepFlow1::trackDef(node)
181+
or
182+
result = DeepFlow2::trackDef(node)
183+
}
184+
185+
module Debug {
186+
query DataFlow::SourceNode trackUseLostAfterForceLocal(DataFlow::SourceNode node) {
187+
result = DeepFlow1::trackUse(node) and
188+
not result = trackUseLocal(node)
189+
}
190+
191+
query DataFlow::SourceNode trackDefLostAfterForceLocal(DataFlow::Node node) {
192+
result = DeepFlow1::trackDef(node) and
193+
not result = trackDefLocal(node)
194+
}
195+
196+
query predicate trackUseSecondPass = DeepFlow2::trackUse/1;
197+
198+
query predicate trackDefSecondPass = DeepFlow2::trackDef/1;
199+
200+
query DataFlow::SourceNode trackUseLost(DataFlow::SourceNode node) {
201+
result = DeepFlow1::trackUse(node) and
202+
not result = trackUseFinal(node)
203+
}
204+
205+
query DataFlow::SourceNode trackDefLost(DataFlow::Node node) {
206+
result = DeepFlow1::trackDef(node) and
207+
not result = trackDefFinal(node)
208+
}
209+
210+
query DataFlow::SourceNode trackUseGained(DataFlow::SourceNode node) {
211+
not result = DeepFlow1::trackUse(node) and
212+
result = trackUseFinal(node)
213+
}
214+
215+
query DataFlow::SourceNode trackDefGained(DataFlow::Node node) {
216+
not result = DeepFlow1::trackDef(node) and
217+
result = trackDefFinal(node)
218+
}
219+
}
220+
}

0 commit comments

Comments
 (0)