|
6 | 6 | private import semmle.code.cpp.controlflow.Guards |
7 | 7 | private import semmle.code.cpp.valuenumbering.GlobalValueNumbering |
8 | 8 |
|
9 | | -private newtype TCondition = |
10 | | - TTrue() or |
11 | | - TLogicalCondition(LogicalGuardCondition guard, boolean testIsTrue) { testIsTrue = [false, true] } |
12 | | - |
13 | 9 | /** A `GuardCondition` which appear in a control-flow path to a sink. */ |
14 | 10 | abstract private class LogicalGuardCondition extends GuardCondition { |
15 | 11 | LogicalGuardCondition() { |
@@ -65,84 +61,58 @@ private class NotGuardCondition extends LogicalGuardCondition, NotExpr { |
65 | 61 | } |
66 | 62 | } |
67 | 63 |
|
68 | | -/** A condition that either the trivial `True` condition, or a complex `LogicalCondition`. */ |
69 | | -abstract private class Condition extends TCondition { |
70 | | - abstract string toString(); |
| 64 | +private newtype TCondition = |
| 65 | + MkCondition(LogicalGuardCondition guard, boolean testIsTrue) { testIsTrue = [false, true] } |
| 66 | + |
| 67 | +private class Condition extends MkCondition { |
| 68 | + boolean testIsTrue; |
| 69 | + LogicalGuardCondition guard; |
| 70 | + |
| 71 | + Condition() { this = MkCondition(guard, testIsTrue) } |
71 | 72 |
|
72 | 73 | /** |
73 | 74 | * Holds if this condition having the value `this.getTruthValue()` implies that `cond` has truth |
74 | 75 | * value `cond.getTruthValue()`. |
75 | 76 | */ |
76 | | - pragma[nomagic] |
77 | | - abstract predicate impliesCondition(Condition cond); |
| 77 | + string toString() { result = guard.toString() + " == " + testIsTrue.toString() } |
78 | 78 |
|
79 | 79 | /** Gets the value of this `Condition`. */ |
80 | | - abstract boolean getTruthValue(); |
81 | | - |
82 | | - /** Gets the negated expression represented by this `Condition`, if any. */ |
83 | | - Condition negate() { none() } |
84 | | - |
85 | | - /** |
86 | | - * Holds if this condition having the value `this.getTruthValue()` implies that `cond` cannot have |
87 | | - * the truth value `cond.getTruthValue()`. |
88 | | - */ |
89 | | - final predicate refutesCondition(Condition cond) { this.impliesCondition(cond.negate()) } |
90 | | - |
91 | | - /** Gets the `Location` of the expression that generated this `Condition`, if any. */ |
92 | | - Location getLocation() { none() } |
93 | | -} |
94 | | - |
95 | | -private class True extends Condition, TTrue { |
96 | | - True() { this = TTrue() } |
97 | | - |
98 | | - override string toString() { result = "True" } |
99 | | - |
100 | | - override boolean getTruthValue() { result = true } |
101 | | - |
102 | | - override predicate impliesCondition(Condition cond) { cond instanceof True } |
103 | | -} |
104 | | - |
105 | | -private class LogicalCondition extends Condition, TLogicalCondition { |
106 | | - boolean testIsTrue; |
107 | | - LogicalGuardCondition guard; |
108 | | - |
109 | | - LogicalCondition() { this = TLogicalCondition(guard, testIsTrue) } |
110 | | - |
111 | | - override string toString() { result = guard.toString() + " == " + testIsTrue.toString() } |
112 | | - |
113 | | - override boolean getTruthValue() { result = testIsTrue } |
| 80 | + boolean getTruthValue() { result = testIsTrue } |
114 | 81 |
|
115 | 82 | LogicalGuardCondition getCondition() { result = guard } |
116 | 83 |
|
117 | | - override predicate impliesCondition(Condition cond) { |
118 | | - cond instanceof True |
119 | | - or |
| 84 | + pragma[nomagic] |
| 85 | + predicate impliesCondition(Condition cond) { |
120 | 86 | exists(LogicalGuardCondition other | |
121 | | - other = cond.(LogicalCondition).getCondition() and |
| 87 | + other = cond.getCondition() and |
122 | 88 | this.getCondition() |
123 | 89 | .impliesCondition(globalValueNumber(other).getAnExpr(), |
124 | 90 | pragma[only_bind_into](pragma[only_bind_out](testIsTrue)), |
125 | 91 | pragma[only_bind_into](pragma[only_bind_out](cond.getTruthValue()))) |
126 | 92 | ) |
127 | 93 | } |
128 | 94 |
|
129 | | - override LogicalCondition negate() { |
| 95 | + /** Gets the negated expression represented by this `Condition`, if any. */ |
| 96 | + private Condition negate() { |
130 | 97 | result.getCondition() = guard and |
131 | 98 | result.getTruthValue() = testIsTrue.booleanNot() |
132 | 99 | } |
133 | 100 |
|
134 | | - override Location getLocation() { result = guard.getLocation() } |
| 101 | + /** |
| 102 | + * Holds if this condition having the value `this.getTruthValue()` implies that `cond` cannot have |
| 103 | + * the truth value `cond.getTruthValue()`. |
| 104 | + */ |
| 105 | + final predicate refutesCondition(Condition cond) { this.impliesCondition(cond.negate()) } |
| 106 | + |
| 107 | + /** Gets the `Location` of the expression that generated this `Condition`. */ |
| 108 | + Location getLocation() { result = guard.getLocation() } |
135 | 109 | } |
136 | 110 |
|
137 | 111 | /** |
138 | | - * Gets a `Condition` that controls `b`. |
139 | | - * |
140 | | - * Note: The trivial `True` condition always controls `b`. |
| 112 | + * Gets a `Condition` that controls `b`. That is, to enter `b` the condition must hold. |
141 | 113 | */ |
142 | 114 | private Condition getADirectCondition(BasicBlock b) { |
143 | | - result instanceof True |
144 | | - or |
145 | | - result.(LogicalCondition).getCondition().controls(b, result.(LogicalCondition).getTruthValue()) |
| 115 | + result.getCondition().controls(b, result.getTruthValue()) |
146 | 116 | } |
147 | 117 |
|
148 | 118 | /** |
@@ -365,20 +335,14 @@ abstract class StackVariableReachability extends string { |
365 | 335 | private Condition getASinkCondition(SemanticStackVariable v) { |
366 | 336 | exists(BasicBlock bb | |
367 | 337 | revBbEntryReachesLocally(bb, v, _, this) and |
368 | | - result |
369 | | - .(LogicalCondition) |
370 | | - .getCondition() |
371 | | - .controls(bb, result.(LogicalCondition).getTruthValue()) |
| 338 | + result.getCondition().controls(bb, result.getTruthValue()) |
372 | 339 | ) |
373 | 340 | } |
374 | 341 |
|
375 | 342 | private Condition getABarrierCondition(SemanticStackVariable v) { |
376 | 343 | exists(BasicBlock bb | |
377 | 344 | isBarrier(bb.getANode(), v) and |
378 | | - result |
379 | | - .(LogicalCondition) |
380 | | - .getCondition() |
381 | | - .controls(bb, result.(LogicalCondition).getTruthValue()) |
| 345 | + result.getCondition().controls(bb, result.getTruthValue()) |
382 | 346 | ) |
383 | 347 | } |
384 | 348 |
|
@@ -409,12 +373,11 @@ abstract class StackVariableReachability extends string { |
409 | 373 | ) |
410 | 374 | ) |
411 | 375 | or |
412 | | - exists(BasicBlock pred, LogicalCondition cond | |
| 376 | + exists(BasicBlock pred | |
413 | 377 | pred.getASuccessor() = bb and |
414 | | - cond = getACondition(source, v, pred) and |
| 378 | + result = getACondition(source, v, pred) and |
415 | 379 | revBbSuccessorEntryReaches0(source, pred, v, _, this) and |
416 | | - result = cond and |
417 | | - exists(LogicalGuardCondition c | c = cond.getCondition() | |
| 380 | + exists(LogicalGuardCondition c | c = result.getCondition() | |
418 | 381 | not isLoopCondition(c, pred, bb) and |
419 | 382 | not isDisjunctionCondition(c, pred, bb) and |
420 | 383 | not isLoopVariantCondition(c, pred, bb) |
@@ -451,14 +414,14 @@ abstract class StackVariableReachability extends string { |
451 | 414 | // another path condition that refutes that the condition is true. |
452 | 415 | succ = pred.getATrueSuccessor() and |
453 | 416 | not exists(Condition cond | cond = getACondition(source, v, pred) | |
454 | | - cond.refutesCondition(TLogicalCondition(pred.getEnd(), true)) |
| 417 | + cond.refutesCondition(MkCondition(pred.getEnd(), true)) |
455 | 418 | ) |
456 | 419 | or |
457 | 420 | // If we picked the successor edge corresponding to a condition being false, there must not be |
458 | 421 | // another path condition that refutes that the condition is false. |
459 | 422 | succ = pred.getAFalseSuccessor() and |
460 | 423 | not exists(Condition cond | cond = getACondition(source, v, pred) | |
461 | | - cond.refutesCondition(TLogicalCondition(pred.getEnd(), false)) |
| 424 | + cond.refutesCondition(MkCondition(pred.getEnd(), false)) |
462 | 425 | ) |
463 | 426 | or |
464 | 427 | // If it wasn't a conditional successor edge we require nothing. |
|
0 commit comments