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

Skip to content

Commit 01ca63a

Browse files
committed
C++: Bring back StackVariableReachability.qll
This is now a copy of `LocalScopeVariableReachability.qll`, just with `s/LocalScopeVariable/StackVariable/g`. It can be used as a drop-in replacement since the `LocalScopeVariableReachability.qll` library implementation was already restricted to `SemanticStackVariable`.
1 parent 8110039 commit 01ca63a

1 file changed

Lines changed: 77 additions & 42 deletions

File tree

cpp/ql/src/semmle/code/cpp/controlflow/StackVariableReachability.qll

Lines changed: 77 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
import cpp
22

33
/**
4-
* DEPRECATED: use `LocalScopeVariableReachability` instead.
5-
*
64
* A reachability analysis for control-flow nodes involving stack variables.
5+
* This defines sources, sinks, and any other configurable aspect of the
6+
* analysis. Multiple analyses can coexist. To create an analysis, extend this
7+
* class with a subclass whose characteristic predicate is a unique singleton
8+
* string. For example, write
9+
*
10+
* ```
11+
* class MyAnalysisConfiguration extends StackVariableReachability {
12+
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
13+
* // Override `isSource` and `isSink`.
14+
* // Override `isBarrier`.
15+
* }
16+
* ```
17+
*
18+
* Then, to query whether there is flow between some source and sink, call the
19+
* `reaches` predicate on an instance of `MyAnalysisConfiguration`.
720
*/
8-
abstract deprecated class StackVariableReachability extends string {
21+
abstract class StackVariableReachability extends string {
922
bindingset[this]
1023
StackVariableReachability() { length() >= 0 }
1124

@@ -24,13 +37,13 @@ abstract deprecated class StackVariableReachability extends string {
2437
* uses basic blocks internally for better performance:
2538
*
2639
* ```
27-
* predicate reaches(ControlFlowNode source, StackVariable v, ControlFlowNode sink) {
40+
* predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
2841
* reachesImpl(source, v, sink)
2942
* and
3043
* isSink(sink, v)
3144
* }
3245
*
33-
* predicate reachesImpl(ControlFlowNode source, StackVariable v, ControlFlowNode sink) {
46+
* predicate reachesImpl(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
3447
* sink = source.getASuccessor() and isSource(source, v)
3548
* or
3649
* exists(ControlFlowNode mid | reachesImpl(source, v, mid) |
@@ -44,7 +57,7 @@ abstract deprecated class StackVariableReachability extends string {
4457
* In addition to using a better performing implementation, this analysis
4558
* accounts for loops where the condition is provably true upon entry.
4659
*/
47-
predicate reaches(ControlFlowNode source, StackVariable v, ControlFlowNode sink) {
60+
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
4861
/*
4962
* Implementation detail: the predicates in this class are a generalization of
5063
* those in DefinitionsAndUses.qll, and should be kept in sync.
@@ -71,7 +84,8 @@ abstract deprecated class StackVariableReachability extends string {
7184
}
7285

7386
private predicate bbSuccessorEntryReaches(
74-
BasicBlock bb, StackVariable v, ControlFlowNode node, boolean skipsFirstLoopAlwaysTrueUponEntry
87+
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
88+
boolean skipsFirstLoopAlwaysTrueUponEntry
7589
) {
7690
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
7791
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
@@ -85,11 +99,22 @@ abstract deprecated class StackVariableReachability extends string {
8599
)
86100
}
87101

88-
private predicate bbEntryReachesLocally(BasicBlock bb, StackVariable v, ControlFlowNode node) {
89-
exists(int n | node = bb.getNode(n) and isSink(node, v) |
90-
not exists(int m | m < n | isBarrier(bb.getNode(m), v))
102+
private predicate bbEntryReachesLocally(
103+
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
104+
) {
105+
exists(int n |
106+
node = bb.getNode(n) and
107+
isSink(node, v)
108+
|
109+
not exists(this.firstBarrierIndexIn(bb, v))
110+
or
111+
n <= this.firstBarrierIndexIn(bb, v)
91112
)
92113
}
114+
115+
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
116+
result = min(int m | isBarrier(bb.getNode(m), v))
117+
}
93118
}
94119

95120
/**
@@ -113,26 +138,32 @@ private predicate bbLoopEntryConditionAlwaysTrueAt(BasicBlock bb, int i, Control
113138
}
114139

115140
/**
116-
* Basic block `pred` ends with a condition belonging to a loop, and that
117-
* condition is provably true upon entry. Basic block `succ` is a successor
118-
* of `pred`, and `skipsLoop` indicates whether `succ` is the false-successor
119-
* of `pred`.
141+
* Basic block `pred` contains all or part of the condition belonging to a loop,
142+
* and there is an edge from `pred` to `succ` that concludes the condition.
143+
* If the edge corrseponds with the loop condition being found to be `true`, then
144+
* `skipsLoop` is `false`. Otherwise the edge corresponds with the loop condition
145+
* being found to be `false` and `skipsLoop` is `true`. Non-concluding edges
146+
* within a complex loop condition are not matched by this predicate.
120147
*/
121148
private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(
122149
BasicBlock pred, BasicBlock succ, boolean skipsLoop
123150
) {
124-
succ = pred.getASuccessor() and
125-
exists(ControlFlowNode last |
126-
last = pred.getEnd() and
127-
loopConditionAlwaysTrueUponEntry(_, last) and
128-
if succ = pred.getAFalseSuccessor() then skipsLoop = true else skipsLoop = false
151+
exists(Expr cond |
152+
loopConditionAlwaysTrueUponEntry(_, cond) and
153+
cond.getAChild*() = pred.getEnd() and
154+
succ = pred.getASuccessor() and
155+
not cond.getAChild*() = succ.getStart() and
156+
(
157+
succ = pred.getAFalseSuccessor() and
158+
skipsLoop = true
159+
or
160+
succ = pred.getATrueSuccessor() and
161+
skipsLoop = false
162+
)
129163
)
130164
}
131165

132166
/**
133-
* DEPRECATED: use the corresponding predicate in
134-
* `LocalScopeVariableReachability` instead.
135-
*
136167
* Loop invariant for `bbSuccessorEntryReaches`:
137168
*
138169
* - `succ` is a successor of `pred`.
@@ -146,7 +177,7 @@ private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(
146177
* is provably true upon entry, then `succ` is not allowed to skip
147178
* that loop (`succSkipsFirstLoopAlwaysTrueUponEntry = false`).
148179
*/
149-
deprecated predicate bbSuccessorEntryReachesLoopInvariant(
180+
predicate bbSuccessorEntryReachesLoopInvariant(
150181
BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry,
151182
boolean succSkipsFirstLoopAlwaysTrueUponEntry
152183
) {
@@ -162,7 +193,7 @@ deprecated predicate bbSuccessorEntryReachesLoopInvariant(
162193
// The edge from `pred` to `succ` is _not_ from a loop condition provably
163194
// true upon entry, so the values of `predSkipsFirstLoopAlwaysTrueUponEntry`
164195
// and `succSkipsFirstLoopAlwaysTrueUponEntry` must be the same.
165-
not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, _, _) and
196+
not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, _) and
166197
succSkipsFirstLoopAlwaysTrueUponEntry = predSkipsFirstLoopAlwaysTrueUponEntry and
167198
// Moreover, if `pred` contains the entry point of a loop where the
168199
// condition is provably true upon entry, then `succ` is not allowed
@@ -176,13 +207,16 @@ deprecated predicate bbSuccessorEntryReachesLoopInvariant(
176207
}
177208

178209
/**
179-
* DEPRECATED: use `LocalScopeVariableReachabilityWithReassignment` instead.
180-
*
181210
* Reachability analysis for control-flow nodes involving stack variables.
182211
* Unlike `StackVariableReachability`, this analysis takes variable
183212
* reassignments into account.
213+
*
214+
* This class is used like `StackVariableReachability`, except that
215+
* subclasses should override `isSourceActual` and `isSinkActual` instead of
216+
* `isSource` and `isSink`, and that there is a `reachesTo` predicate in
217+
* addition to `reaches`.
184218
*/
185-
abstract deprecated class StackVariableReachabilityWithReassignment extends StackVariableReachability {
219+
abstract class StackVariableReachabilityWithReassignment extends StackVariableReachability {
186220
bindingset[this]
187221
StackVariableReachabilityWithReassignment() { length() >= 0 }
188222

@@ -199,19 +233,19 @@ abstract deprecated class StackVariableReachabilityWithReassignment extends Stac
199233
* performance:
200234
*
201235
* ```
202-
* predicate reaches(ControlFlowNode source, StackVariable v, ControlFlowNode sink) {
236+
* predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
203237
* reachesImpl(source, v, sink)
204238
* and
205239
* isSinkActual(sink, v)
206240
* }
207241
*
208-
* predicate reachesImpl(ControlFlowNode source, StackVariable v, ControlFlowNode sink) {
242+
* predicate reachesImpl(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
209243
* isSourceActual(source, v)
210244
* and
211245
* (
212246
* sink = source.getASuccessor()
213247
* or
214-
* exists(ControlFlowNode mid, StackVariable v0 | reachesImpl(source, v0, mid) |
248+
* exists(ControlFlowNode mid, SemanticStackVariable v0 | reachesImpl(source, v0, mid) |
215249
* // ordinary successor
216250
* not isBarrier(mid, v) and
217251
* sink = mid.getASuccessor() and
@@ -228,15 +262,15 @@ abstract deprecated class StackVariableReachabilityWithReassignment extends Stac
228262
* In addition to using a better performing implementation, this analysis
229263
* accounts for loops where the condition is provably true upon entry.
230264
*/
231-
override predicate reaches(ControlFlowNode source, StackVariable v, ControlFlowNode sink) {
265+
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
232266
reachesTo(source, v, sink, _)
233267
}
234268

235269
/**
236270
* As `reaches`, but also specifies the last variable it was reassigned to (`v0`).
237271
*/
238272
predicate reachesTo(
239-
ControlFlowNode source, StackVariable v, ControlFlowNode sink, StackVariable v0
273+
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
240274
) {
241275
exists(ControlFlowNode def |
242276
actualSourceReaches(source, v, def, v0) and
@@ -246,17 +280,19 @@ abstract deprecated class StackVariableReachabilityWithReassignment extends Stac
246280
}
247281

248282
private predicate actualSourceReaches(
249-
ControlFlowNode source, StackVariable v, ControlFlowNode def, StackVariable v0
283+
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
250284
) {
251285
isSourceActual(source, v) and def = source and v0 = v
252286
or
253-
exists(ControlFlowNode source1, StackVariable v1 | actualSourceReaches(source, v, source1, v1) |
287+
exists(ControlFlowNode source1, SemanticStackVariable v1 |
288+
actualSourceReaches(source, v, source1, v1)
289+
|
254290
reassignment(source1, v1, def, v0)
255291
)
256292
}
257293

258294
private predicate reassignment(
259-
ControlFlowNode source, StackVariable v, ControlFlowNode def, StackVariable v0
295+
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
260296
) {
261297
StackVariableReachability.super.reaches(source, v, def) and
262298
exprDefinition(v0, def, v.getAnAccess())
@@ -278,13 +314,12 @@ abstract deprecated class StackVariableReachabilityWithReassignment extends Stac
278314
}
279315

280316
/**
281-
* DEPRECATED: use `LocalScopeVariableReachabilityExt` instead.
282-
*
283317
* Same as `StackVariableReachability`, but `isBarrier` works on control-flow
284318
* edges rather than nodes and is therefore parameterized by the original
285-
* source node as well.
319+
* source node as well. Otherwise, this class is used like
320+
* `StackVariableReachability`.
286321
*/
287-
abstract deprecated class StackVariableReachabilityExt extends string {
322+
abstract class StackVariableReachabilityExt extends string {
288323
bindingset[this]
289324
StackVariableReachabilityExt() { length() >= 0 }
290325

@@ -300,7 +335,7 @@ abstract deprecated class StackVariableReachabilityExt extends string {
300335
);
301336

302337
/** See `StackVariableReachability.reaches`. */
303-
predicate reaches(ControlFlowNode source, StackVariable v, ControlFlowNode sink) {
338+
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
304339
exists(BasicBlock bb, int i |
305340
isSource(source, v) and
306341
bb.getNode(i) = source and
@@ -321,7 +356,7 @@ abstract deprecated class StackVariableReachabilityExt extends string {
321356
}
322357

323358
private predicate bbSuccessorEntryReaches(
324-
ControlFlowNode source, BasicBlock bb, StackVariable v, ControlFlowNode node,
359+
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
325360
boolean skipsFirstLoopAlwaysTrueUponEntry
326361
) {
327362
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
@@ -338,7 +373,7 @@ abstract deprecated class StackVariableReachabilityExt extends string {
338373
}
339374

340375
private predicate bbEntryReachesLocally(
341-
ControlFlowNode source, BasicBlock bb, StackVariable v, ControlFlowNode node
376+
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
342377
) {
343378
isSource(source, v) and
344379
exists(int n | node = bb.getNode(n) and isSink(node, v) |

0 commit comments

Comments
 (0)