11import 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 */
121148private 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