Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e6a1374

Browse files
committed
JS: Make separate type for back-tracking types
1 parent 0b2c946 commit e6a1374

2 files changed

Lines changed: 78 additions & 7 deletions

File tree

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,19 +160,24 @@ class SourceNode extends DataFlow::Node {
160160
*
161161
* See `TypeTracker` for more details about how to use this.
162162
*/
163-
DataFlow::SourceNode track(TypeTracker src, TypeTracker dst) {
163+
DataFlow::SourceNode track(TypeTracker t2, TypeTracker t) {
164164
exists(StepSummary summary |
165165
StepSummary::step(this, result, summary) and
166-
dst = StepSummary::append(src, summary)
166+
t = StepSummary::append(t2, summary)
167167
)
168168
}
169169

170170
/**
171171
* Gets a node that may flow into this one using one heap and/or interprocedural step.
172172
*
173-
* See `TypeTracker` for more details about how to use this.
173+
* See `TypeBackTracker` for more details about how to use this.
174174
*/
175-
DataFlow::SourceNode backtrack(TypeTracker src, TypeTracker dst) { this = result.track(src, dst) }
175+
DataFlow::SourceNode backtrack(TypeBackTracker t2, TypeBackTracker t) {
176+
exists(StepSummary summary |
177+
StepSummary::step(result, this, summary) and
178+
t = StepSummary::prepend(summary, t2)
179+
)
180+
}
176181
}
177182

178183
module SourceNode {

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

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ module StepSummary {
118118
not (type.hasCall() = true and summary.hasReturn() = true) and
119119
result.hasCall() = type.hasCall().booleanOr(summary.hasCall())
120120
}
121+
122+
/**
123+
* INTERNAL. Do not use.
124+
*
125+
* Prepends a step summary before a backwards type-tracking summary.
126+
*/
127+
TypeBackTracker prepend(StepSummary summary, TypeBackTracker type) {
128+
not (type.hasReturn() = true and summary.hasCall() = true) and
129+
result.hasReturn() = type.hasReturn().booleanOr(summary.hasReturn())
130+
}
121131
}
122132

123133
private newtype TTypeTracker = MkTypeTracker(boolean hasCall) {
@@ -147,9 +157,8 @@ private newtype TTypeTracker = MkTypeTracker(boolean hasCall) {
147157
* DataFlow::SourceNode myType() { result = myType(_) }
148158
* ```
149159
*
150-
* This class can also be used to track values backwards, which can be useful for tracking
151-
* the type of a callback. To do so, use the example above except with `.track`
152-
* replaced with `.backtrack`.
160+
* To track values backwards, which can be useful for tracking
161+
* the type of a callback, use the `TypeBackTracker` class instead.
153162
*/
154163
class TypeTracker extends TTypeTracker {
155164
Boolean hasCall;
@@ -178,3 +187,60 @@ class TypeTracker extends TTypeTracker {
178187
result = hasCall
179188
}
180189
}
190+
191+
private newtype TTypeBackTracker = MkTypeBackTracker(boolean hasReturn) {
192+
hasReturn = true or hasReturn = false
193+
}
194+
195+
/**
196+
* Summary of the steps needed to back-track a use of a value to a given dataflow node.
197+
*
198+
* This can be used to track callbacks that are passed to a certian API call, and are
199+
* therefore expected to called with a certain type of value.
200+
*
201+
* Note that type back-tracking does not provide a source/sink relation, that is,
202+
* it may determine that a node will be used in an API call somwwhere, but it won't
203+
* determine exactly where that use was, or the path that led to the use.
204+
*
205+
* It is recommended that all uses of this type is written on the following form,
206+
* for back-tracking some callback type `myCallback`:
207+
* ```
208+
* DataFlow::SourceNode myCallback(DataFlow::TypeBackTracker t) {
209+
* t.start() and
210+
* result = (< some API call >).getParameter(< n >).getALocalSource()
211+
* or
212+
* exists (DataFlow::TypeTracker t2 |
213+
* result = myCallback(t2).backtrack(t2, t)
214+
* )
215+
* }
216+
*
217+
* DataFlow::SourceNode myCallback() { result = myCallback(_) }
218+
* ```
219+
*/
220+
class TypeBackTracker extends TTypeBackTracker {
221+
Boolean hasReturn;
222+
223+
TypeBackTracker() { this = MkTypeBackTracker(hasReturn) }
224+
225+
string toString() {
226+
hasReturn = true and result = "type back-tracker with return steps"
227+
or
228+
hasReturn = false and result = "type back-tracker without return steps"
229+
}
230+
231+
/**
232+
* Holds if this is the starting point of type tracking.
233+
*/
234+
predicate start() {
235+
hasReturn = false
236+
}
237+
238+
/**
239+
* INTERNAL. DO NOT USE.
240+
*
241+
* Holds if this type has been back-tracked into a call through return edge.
242+
*/
243+
boolean hasReturn() {
244+
result = hasReturn
245+
}
246+
}

0 commit comments

Comments
 (0)