Skip to content

Commit 7145a57

Browse files
committed
refactor StepSummary into an internal .qll
1 parent cd6fe81 commit 7145a57

File tree

5 files changed

+185
-170
lines changed

5 files changed

+185
-170
lines changed

javascript/ql/src/semmle/javascript/Promises.qll

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import javascript
6+
private import dataflow.internal.StepSummary
67

78
/**
89
* A definition of a `Promise` object.
@@ -165,26 +166,37 @@ module PromiseTypeTracking {
165166
/**
166167
* Gets the result from a single step through a promise, from `pred` to `result` summarized by `summary`.
167168
* This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another.
168-
*
169-
* See the qldoc for the `PromiseTypeTracking` module for an example of how to use this predicate.
170169
*/
171-
DataFlow::SourceNode promiseStep(DataFlow::SourceNode pred, DataFlow::StepSummary summary) {
170+
DataFlow::SourceNode promiseStep(DataFlow::SourceNode pred, StepSummary summary) {
172171
exists(PromiseFlowStep step, string field | field = Promises::valueProp() |
173-
summary = DataFlow::LoadStep(field) and
172+
summary = LoadStep(field) and
174173
step.load(pred, result, field)
175174
or
176-
summary = DataFlow::StoreStep(field) and
175+
summary = StoreStep(field) and
177176
step.store(pred, result, field)
178177
or
179-
summary = DataFlow::LevelStep() and
178+
summary = LevelStep() and
180179
step.loadStore(pred, result, field)
181180
)
182181
}
183182

183+
/**
184+
* Gets the result from a single step through a promise, from `pred` with tracker `t2` to `result` with tracker `t`.
185+
* This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another.
186+
*/
187+
DataFlow::SourceNode promiseStep(
188+
DataFlow::SourceNode pred, DataFlow::TypeTracker t, DataFlow::TypeTracker t2
189+
) {
190+
exists(StepSummary summary |
191+
result = PromiseTypeTracking::promiseStep(pred, summary) and
192+
t = t2.append(summary)
193+
)
194+
}
195+
184196
/**
185197
* A class enabling the use of the `resolveField` as a pseudo-property in type-tracking predicates.
186198
*/
187-
private class ResolveFieldAsTypeTrackingProperty extends DataFlow::TypeTrackingPseudoProperty {
199+
private class ResolveFieldAsTypeTrackingProperty extends TypeTrackingPseudoProperty {
188200
ResolveFieldAsTypeTrackingProperty() { this = Promises::valueProp() }
189201
}
190202
}

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

Lines changed: 1 addition & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -8,160 +8,7 @@
88

99
private import javascript
1010
private import internal.FlowSteps
11-
12-
private class PropertyName extends string {
13-
PropertyName() {
14-
this = any(DataFlow::PropRef pr).getPropertyName()
15-
or
16-
AccessPath::isAssignedInUniqueFile(this)
17-
or
18-
exists(AccessPath::getAnAssignmentTo(_, this))
19-
or
20-
this instanceof TypeTrackingPseudoProperty
21-
}
22-
}
23-
24-
/**
25-
* A pseudo-property that can be used in type-tracking.
26-
*/
27-
abstract class TypeTrackingPseudoProperty extends string {
28-
bindingset[this]
29-
TypeTrackingPseudoProperty() { any() }
30-
}
31-
32-
private class OptionalPropertyName extends string {
33-
OptionalPropertyName() { this instanceof PropertyName or this = "" }
34-
}
35-
36-
/**
37-
* A description of a step on an inter-procedural data flow path.
38-
*/
39-
newtype TStepSummary =
40-
LevelStep() or
41-
CallStep() or
42-
ReturnStep() or
43-
StoreStep(PropertyName prop) or
44-
LoadStep(PropertyName prop)
45-
46-
/**
47-
* INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
48-
*
49-
* A description of a step on an inter-procedural data flow path.
50-
*/
51-
class StepSummary extends TStepSummary {
52-
/** Gets a textual representation of this step summary. */
53-
string toString() {
54-
this instanceof LevelStep and result = "level"
55-
or
56-
this instanceof CallStep and result = "call"
57-
or
58-
this instanceof ReturnStep and result = "return"
59-
or
60-
exists(string prop | this = StoreStep(prop) | result = "store " + prop)
61-
or
62-
exists(string prop | this = LoadStep(prop) | result = "load " + prop)
63-
}
64-
}
65-
66-
module StepSummary {
67-
/**
68-
* INTERNAL: Use `SourceNode.track()` or `SourceNode.backtrack()` instead.
69-
*/
70-
cached
71-
predicate step(DataFlow::SourceNode pred, DataFlow::SourceNode succ, StepSummary summary) {
72-
exists(DataFlow::Node mid | pred.flowsTo(mid) | smallstep(mid, succ, summary))
73-
}
74-
75-
/**
76-
* INTERNAL: Use `TypeBackTracker.smallstep()` instead.
77-
*/
78-
predicate smallstep(DataFlow::Node pred, DataFlow::Node succ, StepSummary summary) {
79-
// Flow through properties of objects
80-
propertyFlowStep(pred, succ) and
81-
summary = LevelStep()
82-
or
83-
// Flow through global variables
84-
globalFlowStep(pred, succ) and
85-
summary = LevelStep()
86-
or
87-
// Flow into function
88-
callStep(pred, succ) and
89-
summary = CallStep()
90-
or
91-
// Flow out of function
92-
returnStep(pred, succ) and
93-
summary = ReturnStep()
94-
or
95-
// Flow through an instance field between members of the same class
96-
DataFlow::localFieldStep(pred, succ) and
97-
summary = LevelStep()
98-
or
99-
exists(string prop |
100-
basicStoreStep(pred, succ, prop) and
101-
summary = StoreStep(prop)
102-
or
103-
basicLoadStep(pred, succ, prop) and
104-
summary = LoadStep(prop)
105-
)
106-
or
107-
any(AdditionalTypeTrackingStep st).step(pred, succ) and
108-
summary = LevelStep()
109-
or
110-
// Store to global access path
111-
exists(string name |
112-
pred = AccessPath::getAnAssignmentTo(name) and
113-
AccessPath::isAssignedInUniqueFile(name) and
114-
succ = DataFlow::globalAccessPathRootPseudoNode() and
115-
summary = StoreStep(name)
116-
)
117-
or
118-
// Load from global access path
119-
exists(string name |
120-
succ = AccessPath::getAReferenceTo(name) and
121-
AccessPath::isAssignedInUniqueFile(name) and
122-
pred = DataFlow::globalAccessPathRootPseudoNode() and
123-
summary = LoadStep(name)
124-
)
125-
or
126-
// Store to non-global access path
127-
exists(string name |
128-
pred = AccessPath::getAnAssignmentTo(succ, name) and
129-
summary = StoreStep(name)
130-
)
131-
or
132-
// Load from non-global access path
133-
exists(string name |
134-
succ = AccessPath::getAReferenceTo(pred, name) and
135-
summary = LoadStep(name) and
136-
name != ""
137-
)
138-
or
139-
// Step in/out of a promise
140-
succ = PromiseTypeTracking::promiseStep(pred, summary)
141-
or
142-
// Summarize calls with flow directly from a parameter to a return.
143-
exists(DataFlow::ParameterNode param, DataFlow::FunctionNode fun |
144-
(
145-
param.flowsTo(fun.getAReturn()) and
146-
summary = LevelStep()
147-
or
148-
exists(string prop |
149-
param.getAPropertyRead(prop).flowsTo(fun.getAReturn()) and
150-
summary = LoadStep(prop)
151-
)
152-
) and
153-
if param = fun.getAParameter()
154-
then
155-
// Step from argument to call site.
156-
argumentPassing(succ, pred, fun.getFunction(), param)
157-
else (
158-
// Step from captured parameter to local call sites
159-
pred = param and
160-
succ = fun.getAnInvocation()
161-
)
162-
)
163-
}
164-
}
11+
private import internal.StepSummary
16512

16613
private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyName prop)
16714

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
private import javascript
6+
private import StepSummary
67

78
cached
89
module CallGraph {
@@ -83,7 +84,7 @@ module CallGraph {
8384
getAFunctionReference(function, 0, t.continue()).flowsTo(callback)
8485
)
8586
or
86-
exists(DataFlow::StepSummary summary, DataFlow::TypeTracker t2 |
87+
exists(StepSummary summary, DataFlow::TypeTracker t2 |
8788
result = getABoundFunctionReferenceAux(function, boundArgs, t2, summary) and
8889
t = t2.append(summary)
8990
)
@@ -92,11 +93,11 @@ module CallGraph {
9293
pragma[noinline]
9394
private DataFlow::SourceNode getABoundFunctionReferenceAux(
9495
DataFlow::FunctionNode function, int boundArgs, DataFlow::TypeTracker t,
95-
DataFlow::StepSummary summary
96+
StepSummary summary
9697
) {
9798
exists(DataFlow::SourceNode prev |
9899
prev = getABoundFunctionReferenceAux(function, boundArgs, t) and
99-
DataFlow::StepSummary::step(prev, result, summary)
100+
StepSummary::step(prev, result, summary)
100101
)
101102
}
102103

0 commit comments

Comments
 (0)