Skip to content

Commit a504ad4

Browse files
authored
Merge pull request #1270 from xiemaisi/odasa/7904
Approved by esben-semmle
2 parents 0917936 + 76e01f0 commit a504ad4

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,7 @@ class SourceNode extends DataFlow::Node {
164164
*/
165165
pragma[inline]
166166
DataFlow::SourceNode track(TypeTracker t2, TypeTracker t) {
167-
exists(StepSummary summary |
168-
StepSummary::step(this, result, summary) and
169-
t = t2.append(summary)
170-
)
167+
t = t2.step(this, result)
171168
}
172169

173170
/**

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

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyNa
101101
* source/sink relation, that is, it may determine that a node has a given type,
102102
* but it won't determine where that type came from.
103103
*
104-
* It is recommended that all uses of this type is written on the following form,
104+
* It is recommended that all uses of this type are written in the following form,
105105
* for tracking some type `myType`:
106106
* ```
107107
* DataFlow::SourceNode myType(DataFlow::TypeTracker t) {
@@ -116,8 +116,12 @@ private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyNa
116116
* DataFlow::SourceNode myType() { result = myType(DataFlow::TypeTracker::end()) }
117117
* ```
118118
*
119-
* To track values backwards, which can be useful for tracking
120-
* the type of a callback, use the `TypeBackTracker` class instead.
119+
* Instead of `result = myType(t2).track(t2, t)`, you can also use the equivalent
120+
* `t = t2.step(myType(t2), result)`. If you additionally want to track individual
121+
* intra-procedural steps, use `t = t2.smallstep(myCallback(t2), result)`.
122+
*
123+
* To track values backwards, which can be useful for tracking the type of a callback,
124+
* use the `TypeBackTracker` class instead.
121125
*/
122126
class TypeTracker extends TTypeTracker {
123127
Boolean hasCall;
@@ -172,6 +176,37 @@ class TypeTracker extends TTypeTracker {
172176
* This predicate is only defined if the type has not been tracked into a property.
173177
*/
174178
TypeTracker continue() { prop = "" and result = this }
179+
180+
/**
181+
* Gets the summary that corresponds to having taken a forwards
182+
* heap and/or inter-procedural step from `pred` to `succ`.
183+
*/
184+
pragma[inline]
185+
TypeTracker step(DataFlow::SourceNode pred, DataFlow::SourceNode succ) {
186+
exists(StepSummary summary |
187+
StepSummary::step(pred, succ, summary) and
188+
result = this.append(summary)
189+
)
190+
}
191+
192+
/**
193+
* Gets the summary that corresponds to having taken a forwards
194+
* local, heap and/or inter-procedural step from `pred` to `succ`.
195+
*
196+
* Unlike `TypeTracker::step`, this predicate exposes all edges
197+
* in the flow graph, and not just the edges between `SourceNode`s.
198+
* It may therefore be less performant.
199+
*/
200+
pragma[inline]
201+
TypeTracker smallstep(DataFlow::Node pred, DataFlow::Node succ) {
202+
exists(StepSummary summary |
203+
StepSummary::smallstep(pred, succ, summary) and
204+
result = this.append(summary)
205+
)
206+
or
207+
succ = pred.getASuccessor() and
208+
result = this
209+
}
175210
}
176211

177212
module TypeTracker {
@@ -192,20 +227,25 @@ private newtype TTypeBackTracker = MkTypeBackTracker(Boolean hasReturn, Optional
192227
* it may determine that a node will be used in an API call somewhere, but it won't
193228
* determine exactly where that use was, or the path that led to the use.
194229
*
195-
* It is recommended that all uses of this type is written on the following form,
230+
* It is recommended that all uses of this type are written in the following form,
196231
* for back-tracking some callback type `myCallback`:
232+
*
197233
* ```
198234
* DataFlow::SourceNode myCallback(DataFlow::TypeBackTracker t) {
199235
* t.start() and
200236
* result = (< some API call >).getArgument(< n >).getALocalSource()
201237
* or
202238
* exists (DataFlow::TypeBackTracker t2 |
203-
* t2 = t.step(result, myCallback(t2))
239+
* result = myCallback(t2).backtrack(t2, t)
204240
* )
205241
* }
206242
*
207243
* DataFlow::SourceNode myCallback() { result = myCallback(DataFlow::TypeBackTracker::end()) }
208244
* ```
245+
*
246+
* Instead of `result = myCallback(t2).backtrack(t2, t)`, you can also use the equivalent
247+
* `t2 = t.step(result, myCallback(t2))`. If you additionally want to track individual
248+
* intra-procedural steps, use `t2 = t.smallstep(result, myCallback(t2))`.
209249
*/
210250
class TypeBackTracker extends TTypeBackTracker {
211251
Boolean hasReturn;

0 commit comments

Comments
 (0)