Skip to content

Commit 1047a89

Browse files
committed
Improve complexity class of getASuccessorSwitchCase
1 parent d99a005 commit 1047a89

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,15 @@ private module ControlFlowGraphImpl {
460460
)
461461
}
462462

463+
private int lastCaseIndex(StmtParent switch) {
464+
result = max(int i | any(SwitchCase c).isNthCaseOf(switch, i))
465+
}
466+
467+
// Join order engineering -- first determine the switch block and the case indices required, then retrieve them.
468+
bindingset[switch, i]
469+
pragma[inline_late]
470+
private predicate isNthCaseOf(StmtParent switch, SwitchCase c, int i) { c.isNthCaseOf(switch, i) }
471+
463472
/**
464473
* Gets a `SwitchCase` that may be `pred`'s direct successor.
465474
*
@@ -469,14 +478,15 @@ private module ControlFlowGraphImpl {
469478
* that any default case comes after the last pattern case.
470479
*/
471480
private SwitchCase getASuccessorSwitchCase(PatternCase pred) {
472-
result.getParent() = pred.getParent() and
473-
result.getIndex() > pred.getIndex() and
474481
// Note we do include `case null, default` (as well as plain old `default`) here.
475482
not result.(ConstCase).getValue(_) instanceof NullLiteral and
476-
(
477-
result.getIndex() <= getNextPatternCase(pred).getIndex()
478-
or
479-
not exists(getNextPatternCase(pred))
483+
exists(int maxCaseIndex, StmtParent switch |
484+
switch = pred.getParent() and
485+
if exists(getNextPatternCase(pred))
486+
then maxCaseIndex = getNextPatternCase(pred).getCaseIndex()
487+
else maxCaseIndex = lastCaseIndex(switch)
488+
|
489+
isNthCaseOf(switch, result, [pred.getCaseIndex() + 1 .. maxCaseIndex])
480490
)
481491
}
482492

java/ql/lib/semmle/code/java/Statement.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,14 @@ class SwitchCase extends Stmt, @case {
464464
this = any(SwitchStmt ss).getCase(result) or this = any(SwitchExpr se).getCase(result)
465465
}
466466

467+
/**
468+
* Holds if this is the `n`th case of switch block `parent`.
469+
*/
470+
pragma[nomagic]
471+
predicate isNthCaseOf(StmtParent parent, int n) {
472+
this.getCaseIndex() = n and this.getParent() = parent
473+
}
474+
467475
/**
468476
* Holds if this `case` is a switch labeled rule of the form `... -> ...`.
469477
*/

0 commit comments

Comments
 (0)