Skip to content

Commit 8270995

Browse files
committed
Shared: Switch case guards to be the case statements.
1 parent f86f191 commit 8270995

File tree

1 file changed

+49
-64
lines changed

1 file changed

+49
-64
lines changed

shared/controlflow/codeql/controlflow/Guards.qll

Lines changed: 49 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,15 @@ signature module InputSig<LocationSig Location> {
106106

107107
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2);
108108

109-
class Expr {
110-
/** Gets a textual representation of this expression. */
109+
class AstNode {
110+
/** Gets a textual representation of this AST node. */
111111
string toString();
112112

113-
/** Gets the location of this expression. */
113+
/** Gets the location of this AST node. */
114114
Location getLocation();
115+
}
115116

117+
class Expr extends AstNode {
116118
/** Gets the associated control flow node. */
117119
ControlFlowNode getControlFlowNode();
118120

@@ -137,12 +139,7 @@ signature module InputSig<LocationSig Location> {
137139

138140
class NonNullExpr extends Expr;
139141

140-
class Case {
141-
/** Gets a textual representation of this switch case. */
142-
string toString();
143-
144-
Location getLocation();
145-
142+
class Case extends AstNode {
146143
Expr getSwitchExpr();
147144

148145
predicate isDefaultCase();
@@ -209,7 +206,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
209206

210207
private newtype TGuardValue =
211208
TValue(TAbstractSingleValue val, Boolean isVal) or
212-
TCaseMatch(Case c, Boolean match) or
213209
TException(Boolean throws)
214210

215211
private class AbstractSingleValue extends TAbstractSingleValue {
@@ -232,19 +228,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
232228
* - null vs. not null
233229
* - true vs. false
234230
* - evaluating to a specific value vs. evaluating to any other value
235-
* - matching a specific case vs. not matching that case
231+
* - throwing an exception vs. not throwing an exception
236232
*/
237233
GuardValue getDualValue() {
238234
exists(AbstractSingleValue val, boolean isVal |
239235
this = TValue(val, isVal) and
240236
result = TValue(val, isVal.booleanNot())
241237
)
242238
or
243-
exists(Case c, boolean match |
244-
this = TCaseMatch(c, match) and
245-
result = TCaseMatch(c, match.booleanNot())
246-
)
247-
or
248239
exists(boolean throws |
249240
this = TException(throws) and
250241
result = TException(throws.booleanNot())
@@ -279,19 +270,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
279270
this = TValue(val, false) and result = "not " + val.toString()
280271
)
281272
or
282-
exists(Case c, boolean match, string s | this = TCaseMatch(c, match) |
283-
(
284-
exists(ConstantExpr ce | c.asConstantCase() = ce and s = ce.toString())
285-
or
286-
not exists(c.asConstantCase()) and s = c.toString()
287-
) and
288-
(
289-
match = true and result = "match " + s
290-
or
291-
match = false and result = "non-match " + s
292-
)
293-
)
294-
or
295273
exists(boolean throws | this = TException(throws) |
296274
throws = true and result = "exception"
297275
or
@@ -348,14 +326,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
348326
exceptionBranchPoint(bb1, _, bb2) and v = TException(true)
349327
}
350328

351-
private predicate caseBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue v, Expr switchExpr) {
352-
exists(Case c | switchExpr = c.getSwitchExpr() |
353-
v = TCaseMatch(c, true) and
354-
c.matchEdge(bb1, bb2)
355-
or
356-
v = TCaseMatch(c, false) and
357-
c.nonMatchEdge(bb1, bb2)
358-
)
329+
private predicate caseBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue v, Case c) {
330+
v = TValue(TValueTrue(), true) and
331+
c.matchEdge(bb1, bb2)
332+
or
333+
v = TValue(TValueTrue(), false) and
334+
c.nonMatchEdge(bb1, bb2)
359335
}
360336

361337
pragma[nomagic]
@@ -366,34 +342,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
366342
eqtest.polarity() = polarity
367343
}
368344

369-
private predicate caseGuard(PreGuard g, Case c, Expr switchExpr) {
370-
g.hasValueBranchEdge(_, _, TCaseMatch(c, _)) and
371-
switchExpr = c.getSwitchExpr()
372-
}
373-
374-
private predicate constcaseEquality(PreGuard g, Expr e1, ConstantExpr e2, GuardValue eqval) {
345+
private predicate constcaseEquality(PreGuard g, Expr e1, ConstantExpr e2) {
375346
exists(Case c |
376-
caseGuard(g, c, e1) and
377-
c.asConstantCase() = e2 and
378-
eqval = TCaseMatch(c, true)
347+
g = c and
348+
e1 = c.getSwitchExpr() and
349+
e2 = c.asConstantCase()
379350
)
380351
}
381352

382-
final private class ExprFinal = Expr;
353+
final private class FinalAstNode = AstNode;
383354

384355
/**
385356
* A guard. This may be any expression whose value determines subsequent
386-
* control flow.
357+
* control flow. It may also be a switch case, which as a guard is considered
358+
* to evaluate to either true or false depending on whether the case matches.
387359
*/
388-
final class PreGuard extends ExprFinal {
360+
final class PreGuard extends FinalAstNode {
389361
/**
390362
* Holds if this guard evaluating to `v` corresponds to taking the edge
391363
* from `bb1` to `bb2`. For ordinary conditional branching this guard is
392364
* the last node in `bb1`, but for switch case matching it is the switch
393365
* expression, which may either be in `bb1` or an earlier basic block.
394366
*/
395367
predicate hasValueBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue v) {
396-
bb1.getLastNode() = this.getControlFlowNode() and
368+
bb1.getLastNode() = this.(Expr).getControlFlowNode() and
397369
branchEdge(bb1, bb2, v)
398370
or
399371
caseBranchEdge(bb1, bb2, v, this)
@@ -434,12 +406,23 @@ module Make<LocationSig Location, InputSig<Location> Input> {
434406
* Holds if this guard tests equality between `e1` and `e2` upon evaluating
435407
* to `eqval`.
436408
*/
437-
predicate isEquality(Expr e1, Expr e2, GuardValue eqval) {
438-
eqtestHasOperands(this, e1, e2, eqval.asBooleanValue())
409+
predicate isEquality(Expr e1, Expr e2, boolean eqval) {
410+
eqtestHasOperands(this, e1, e2, eqval)
439411
or
440-
constcaseEquality(this, e1, e2, eqval)
412+
constcaseEquality(this, e1, e2) and eqval = true
441413
or
442-
constcaseEquality(this, e2, e1, eqval)
414+
constcaseEquality(this, e2, e1) and eqval = true
415+
}
416+
417+
/**
418+
* Gets the basic block of this guard. For expressions, this is the basic
419+
* block of the expression itself, and for switch cases, this is the basic
420+
* block of the expression being compared against the cases.
421+
*/
422+
BasicBlock getBasicBlock() {
423+
result = this.(Expr).getBasicBlock()
424+
or
425+
result = this.(Case).getSwitchExpr().getBasicBlock()
443426
}
444427
}
445428

@@ -457,7 +440,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
457440
g1.(NotExpr).getOperand() = g2 and v1.asBooleanValue().booleanNot() = v2.asBooleanValue()
458441
or
459442
exists(GuardValue eqval, ConstantExpr constant, GuardValue cv |
460-
g1.isEquality(g2, constant, eqval) and
443+
g1.isEquality(g2, constant, eqval.asBooleanValue()) and
461444
constantHasValue(constant, cv)
462445
|
463446
v1 = eqval and v2 = cv
@@ -470,13 +453,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
470453
v2 = TValue(TValueNull(), false)
471454
)
472455
or
473-
exists(Case c1, Case c2, Expr switchExpr |
474-
caseGuard(g1, c1, switchExpr) and
475-
v1 = TCaseMatch(c1, true) and
456+
exists(Case c1, Expr switchExpr |
457+
g1 = c1 and
476458
c1.isDefaultCase() and
477-
caseGuard(g2, c2, switchExpr) and
478-
v2 = TCaseMatch(c2, false) and
479-
c1 != c2
459+
c1.getSwitchExpr() = switchExpr and
460+
v1.asBooleanValue() = true and
461+
g2.(Case).getSwitchExpr() = switchExpr and
462+
v2.asBooleanValue() = false and
463+
g1 != g2
480464
)
481465
}
482466

@@ -965,7 +949,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
965949
module CustomGuard<CustomGuardInputSig CustomGuardInput> {
966950
private import CustomGuardInput
967951

968-
private class ReturnExpr extends ExprFinal {
952+
final private class FinalExpr = Expr;
953+
954+
private class ReturnExpr extends FinalExpr {
969955
ReturnExpr() { any(BooleanMethod m).getAReturnExpr() = this }
970956

971957
pragma[nomagic]
@@ -988,8 +974,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
988974
) {
989975
exists(BooleanMethod m, SsaDefinition param |
990976
m.getAReturnExpr() = ret and
991-
m.getParameter(ppos) = param and
992-
not val instanceof TCaseMatch
977+
m.getParameter(ppos) = param
993978
|
994979
exists(Guard g0, GuardValue v0 |
995980
g0.directlyValueControls(ret.getBasicBlock(), v0) and

0 commit comments

Comments
 (0)