Skip to content

Commit 9fbc0eb

Browse files
author
Max Schaefer
committed
JavaScript: Switch from path summaries to step summaries for type tracking.
This is sufficient since we are not doing summarisation.
1 parent 8e92633 commit 9fbc0eb

File tree

2 files changed

+27
-55
lines changed

2 files changed

+27
-55
lines changed

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

Lines changed: 26 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -10,81 +10,60 @@ import javascript
1010
private import internal.FlowSteps
1111

1212
/**
13-
* A pair of booleans, indicating whether a path goes through a return and/or a call.
14-
*
15-
* Identical to `TPathSummary` except without flow labels.
13+
* A description of a step on an inter-procedural data flow path.
1614
*/
17-
private newtype TStepSummary = MkStepSummary(Boolean hasReturn, Boolean hasCall)
15+
private newtype TStepSummary =
16+
LevelStep() or
17+
CallStep() or
18+
ReturnStep()
1819

1920
/**
2021
* INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
2122
*
22-
* Summary of the steps needed to track a value to a given dataflow node.
23+
* A description of a step on an inter-procedural data flow path.
2324
*/
2425
class StepSummary extends TStepSummary {
25-
Boolean hasReturn;
26-
27-
Boolean hasCall;
28-
29-
StepSummary() { this = MkStepSummary(hasReturn, hasCall) }
30-
31-
/** Indicates whether the path represented by this summary contains any return steps. */
32-
boolean hasReturn() { result = hasReturn }
26+
/** Indicates whether the step represented by this summary is a return. */
27+
boolean hasReturn() { if this instanceof ReturnStep then result = true else result = false }
3328

34-
/** Indicates whether the path represented by this summary contains any call steps. */
35-
boolean hasCall() { result = hasCall }
29+
/** Indicates whether the step represented by this summary is a call. */
30+
boolean hasCall() { if this instanceof CallStep then result = true else result = false }
3631

37-
/** Gets a textual representation of this path summary. */
32+
/** Gets a textual representation of this step summary. */
3833
string toString() {
39-
exists(string withReturn, string withCall |
40-
(if hasReturn = true then withReturn = "with" else withReturn = "without") and
41-
(if hasCall = true then withCall = "with" else withCall = "without")
42-
|
43-
result = "path " + withReturn + " return steps and " + withCall + " call steps"
44-
)
34+
this instanceof LevelStep and result = "level"
35+
or
36+
this instanceof CallStep and result = "call"
37+
or
38+
this instanceof ReturnStep and result = "return"
4539
}
4640
}
4741

4842
module StepSummary {
49-
/**
50-
* Gets a summary describing a path without any calls or returns.
51-
*/
52-
StepSummary level() { result = MkStepSummary(false, false) }
53-
54-
/**
55-
* Gets a summary describing a path with one or more calls, but no returns.
56-
*/
57-
StepSummary call() { result = MkStepSummary(false, true) }
58-
59-
/**
60-
* Gets a summary describing a path with one or more returns, but no calls.
61-
*/
62-
StepSummary return() { result = MkStepSummary(true, false) }
63-
6443
/**
6544
* INTERNAL: Use `SourceNode.track()` or `SourceNode.backtrack()` instead.
6645
*/
6746
predicate step(DataFlow::SourceNode pred, DataFlow::SourceNode succ, StepSummary summary) {
68-
exists (DataFlow::Node predNode | pred.flowsTo(predNode) |
47+
exists(DataFlow::Node predNode | pred.flowsTo(predNode) |
6948
// Flow through properties of objects
7049
propertyFlowStep(predNode, succ) and
71-
summary = level()
50+
summary = LevelStep()
7251
or
7352
// Flow through global variables
7453
globalFlowStep(predNode, succ) and
75-
summary = level()
54+
summary = LevelStep()
7655
or
7756
// Flow into function
7857
callStep(predNode, succ) and
79-
summary = call()
58+
summary = CallStep()
8059
or
8160
// Flow out of function
8261
returnStep(predNode, succ) and
83-
summary = return()
62+
summary = ReturnStep()
8463
or
8564
// Flow through an instance field between members of the same class
8665
DataFlow::localFieldStep(predNode, succ) and
87-
summary = level()
66+
summary = LevelStep()
8867
)
8968
}
9069

@@ -153,18 +132,14 @@ class TypeTracker extends TTypeTracker {
153132
/**
154133
* Holds if this is the starting point of type tracking.
155134
*/
156-
predicate start() {
157-
hasCall = false
158-
}
135+
predicate start() { hasCall = false }
159136

160137
/**
161138
* INTERNAL. DO NOT USE.
162139
*
163140
* Holds if this type has been tracked into a call.
164141
*/
165-
boolean hasCall() {
166-
result = hasCall
167-
}
142+
boolean hasCall() { result = hasCall }
168143
}
169144

170145
private newtype TTypeBackTracker = MkTypeBackTracker(Boolean hasReturn)
@@ -210,16 +185,12 @@ class TypeBackTracker extends TTypeBackTracker {
210185
/**
211186
* Holds if this is the starting point of type tracking.
212187
*/
213-
predicate start() {
214-
hasReturn = false
215-
}
188+
predicate start() { hasReturn = false }
216189

217190
/**
218191
* INTERNAL. DO NOT USE.
219192
*
220193
* Holds if this type has been back-tracked into a call through return edge.
221194
*/
222-
boolean hasReturn() {
223-
result = hasReturn
224-
}
195+
boolean hasReturn() { result = hasReturn }
225196
}

javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ apiObject
55
connection
66
| type tracker with call steps | tst.js:6:15:6:18 | conn |
77
| type tracker with call steps | tst.js:10:5:10:19 | this.connection |
8+
| type tracker with call steps with property connection | tst.js:6:14:6:13 | this |
89
| type tracker without call steps | tst.js:15:10:15:49 | api.cha ... ction() |
910
| type tracker without call steps | tst.js:18:7:18:21 | getConnection() |
1011
| type tracker without call steps | tst.js:30:9:30:23 | getConnection() |

0 commit comments

Comments
 (0)