Skip to content

Commit 63afeb8

Browse files
committed
Shared: Switch case guards to be the case statements.
1 parent 17ccb54 commit 63afeb8

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();
@@ -210,7 +207,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
210207

211208
private newtype TGuardValue =
212209
TValue(TAbstractSingleValue val, Boolean isVal) or
213-
TCaseMatch(Case c, Boolean match) or
214210
TException(Boolean throws)
215211

216212
private class AbstractSingleValue extends TAbstractSingleValue {
@@ -233,19 +229,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
233229
* - null vs. not null
234230
* - true vs. false
235231
* - evaluating to a specific value vs. evaluating to any other value
236-
* - matching a specific case vs. not matching that case
232+
* - throwing an exception vs. not throwing an exception
237233
*/
238234
GuardValue getDualValue() {
239235
exists(AbstractSingleValue val, boolean isVal |
240236
this = TValue(val, isVal) and
241237
result = TValue(val, isVal.booleanNot())
242238
)
243239
or
244-
exists(Case c, boolean match |
245-
this = TCaseMatch(c, match) and
246-
result = TCaseMatch(c, match.booleanNot())
247-
)
248-
or
249240
exists(boolean throws |
250241
this = TException(throws) and
251242
result = TException(throws.booleanNot())
@@ -280,19 +271,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
280271
this = TValue(val, false) and result = "not " + val.toString()
281272
)
282273
or
283-
exists(Case c, boolean match, string s | this = TCaseMatch(c, match) |
284-
(
285-
exists(ConstantExpr ce | c.asConstantCase() = ce and s = ce.toString())
286-
or
287-
not exists(c.asConstantCase()) and s = c.toString()
288-
) and
289-
(
290-
match = true and result = "match " + s
291-
or
292-
match = false and result = "non-match " + s
293-
)
294-
)
295-
or
296274
exists(boolean throws | this = TException(throws) |
297275
throws = true and result = "exception"
298276
or
@@ -349,14 +327,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
349327
exceptionBranchPoint(bb1, _, bb2) and v = TException(true)
350328
}
351329

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

362338
pragma[nomagic]
@@ -367,34 +343,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
367343
eqtest.polarity() = polarity
368344
}
369345

370-
private predicate caseGuard(PreGuard g, Case c, Expr switchExpr) {
371-
g.hasValueBranchEdge(_, _, TCaseMatch(c, _)) and
372-
switchExpr = c.getSwitchExpr()
373-
}
374-
375-
private predicate constcaseEquality(PreGuard g, Expr e1, ConstantExpr e2, GuardValue eqval) {
346+
private predicate constcaseEquality(PreGuard g, Expr e1, ConstantExpr e2) {
376347
exists(Case c |
377-
caseGuard(g, c, e1) and
378-
c.asConstantCase() = e2 and
379-
eqval = TCaseMatch(c, true)
348+
g = c and
349+
e1 = c.getSwitchExpr() and
350+
e2 = c.asConstantCase()
380351
)
381352
}
382353

383-
final private class ExprFinal = Expr;
354+
final private class FinalAstNode = AstNode;
384355

385356
/**
386357
* A guard. This may be any expression whose value determines subsequent
387-
* control flow.
358+
* control flow. It may also be a switch case, which as a guard is considered
359+
* to evaluate to either true or false depending on whether the case matches.
388360
*/
389-
final class PreGuard extends ExprFinal {
361+
final class PreGuard extends FinalAstNode {
390362
/**
391363
* Holds if this guard evaluating to `v` corresponds to taking the edge
392364
* from `bb1` to `bb2`. For ordinary conditional branching this guard is
393365
* the last node in `bb1`, but for switch case matching it is the switch
394366
* expression, which may either be in `bb1` or an earlier basic block.
395367
*/
396368
predicate hasValueBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue v) {
397-
bb1.getLastNode() = this.getControlFlowNode() and
369+
bb1.getLastNode() = this.(Expr).getControlFlowNode() and
398370
branchEdge(bb1, bb2, v)
399371
or
400372
caseBranchEdge(bb1, bb2, v, this)
@@ -435,12 +407,23 @@ module Make<LocationSig Location, InputSig<Location> Input> {
435407
* Holds if this guard tests equality between `e1` and `e2` upon evaluating
436408
* to `eqval`.
437409
*/
438-
predicate isEquality(Expr e1, Expr e2, GuardValue eqval) {
439-
eqtestHasOperands(this, e1, e2, eqval.asBooleanValue())
410+
predicate isEquality(Expr e1, Expr e2, boolean eqval) {
411+
eqtestHasOperands(this, e1, e2, eqval)
440412
or
441-
constcaseEquality(this, e1, e2, eqval)
413+
constcaseEquality(this, e1, e2) and eqval = true
442414
or
443-
constcaseEquality(this, e2, e1, eqval)
415+
constcaseEquality(this, e2, e1) and eqval = true
416+
}
417+
418+
/**
419+
* Gets the basic block of this guard. For expressions, this is the basic
420+
* block of the expression itself, and for switch cases, this is the basic
421+
* block of the expression being compared against the cases.
422+
*/
423+
BasicBlock getBasicBlock() {
424+
result = this.(Expr).getBasicBlock()
425+
or
426+
result = this.(Case).getSwitchExpr().getBasicBlock()
444427
}
445428
}
446429

@@ -458,7 +441,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
458441
g1.(NotExpr).getOperand() = g2 and v1.asBooleanValue().booleanNot() = v2.asBooleanValue()
459442
or
460443
exists(GuardValue eqval, ConstantExpr constant, GuardValue cv |
461-
g1.isEquality(g2, constant, eqval) and
444+
g1.isEquality(g2, constant, eqval.asBooleanValue()) and
462445
constantHasValue(constant, cv)
463446
|
464447
v1 = eqval and v2 = cv
@@ -471,13 +454,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
471454
v2 = TValue(TValueNull(), false)
472455
)
473456
or
474-
exists(Case c1, Case c2, Expr switchExpr |
475-
caseGuard(g1, c1, switchExpr) and
476-
v1 = TCaseMatch(c1, true) and
457+
exists(Case c1, Expr switchExpr |
458+
g1 = c1 and
477459
c1.isDefaultCase() and
478-
caseGuard(g2, c2, switchExpr) and
479-
v2 = TCaseMatch(c2, false) and
480-
c1 != c2
460+
c1.getSwitchExpr() = switchExpr and
461+
v1.asBooleanValue() = true and
462+
g2.(Case).getSwitchExpr() = switchExpr and
463+
v2.asBooleanValue() = false and
464+
g1 != g2
481465
)
482466
}
483467

@@ -970,7 +954,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
970954
module CustomGuard<CustomGuardInputSig CustomGuardInput> {
971955
private import CustomGuardInput
972956

973-
private class ReturnExpr extends ExprFinal {
957+
final private class FinalExpr = Expr;
958+
959+
private class ReturnExpr extends FinalExpr {
974960
ReturnExpr() { any(BooleanMethod m).getAReturnExpr() = this }
975961

976962
pragma[nomagic]
@@ -993,8 +979,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
993979
) {
994980
exists(BooleanMethod m, SsaDefinition param |
995981
m.getAReturnExpr() = ret and
996-
m.getParameter(ppos) = param and
997-
not val instanceof TCaseMatch
982+
m.getParameter(ppos) = param
998983
|
999984
exists(Guard g0, GuardValue v0 |
1000985
g0.directlyValueControls(ret.getBasicBlock(), v0) and

0 commit comments

Comments
 (0)