11import java
22private import semmle.code.java.controlflow.Dominance
33private import semmle.code.java.controlflow.internal.GuardsLogic
4+ private import semmle.code.java.controlflow.internal.Preconditions
45
56/**
67 * A basic block that terminates in a condition, splitting the subsequent control flow.
@@ -71,7 +72,7 @@ class ConditionBlock extends BasicBlock {
7172/**
7273 * A condition that can be evaluated to either true or false. This can either
7374 * be an `Expr` of boolean type that isn't a boolean literal, or a case of a
74- * switch statement.
75+ * switch statement, or a method access that acts as a precondition check .
7576 *
7677 * Evaluating a switch case to true corresponds to taking that switch case, and
7778 * evaluating it to false corresponds to taking some other branch.
@@ -81,6 +82,8 @@ class Guard extends ExprParent {
8182 this .( Expr ) .getType ( ) instanceof BooleanType and not this instanceof BooleanLiteral
8283 or
8384 this instanceof SwitchCase
85+ or
86+ conditionCheck ( this , _)
8487 }
8588
8689 /** Gets the immediately enclosing callable whose body contains this guard. */
@@ -128,6 +131,8 @@ class Guard extends ExprParent {
128131 pred .( Expr ) .getParent * ( ) = sc .getSwitch ( ) .getExpr ( ) and
129132 bb1 = pred .getBasicBlock ( )
130133 )
134+ or
135+ preconditionBranchEdge ( this , bb1 , bb2 , branch )
131136 }
132137
133138 /**
@@ -142,6 +147,8 @@ class Guard extends ExprParent {
142147 )
143148 or
144149 switchCaseControls ( this , controlled ) and branch = true
150+ or
151+ preconditionControls ( this , controlled , branch )
145152 }
146153
147154 /**
@@ -165,6 +172,24 @@ private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
165172 )
166173}
167174
175+ private predicate preconditionBranchEdge (
176+ MethodAccess ma , BasicBlock bb1 , BasicBlock bb2 , boolean branch
177+ ) {
178+ conditionCheck ( ma , branch ) and
179+ bb1 .getLastNode ( ) = ma .getControlFlowNode ( ) and
180+ bb2 = bb1 .getLastNode ( ) .getANormalSuccessor ( )
181+ }
182+
183+ private predicate preconditionControls ( MethodAccess ma , BasicBlock controlled , boolean branch ) {
184+ exists ( BasicBlock check , BasicBlock succ |
185+ preconditionBranchEdge ( ma , check , succ , branch ) and
186+ succ .bbDominates ( controlled ) and
187+ forall ( BasicBlock pred | pred = succ .getABBPredecessor ( ) and pred != check |
188+ succ .bbDominates ( pred )
189+ )
190+ )
191+ }
192+
168193/**
169194 * INTERNAL: Use `Guards.controls` instead.
170195 *
0 commit comments