Java: Deprecate redundant basic block predicates.

This commit is contained in:
Anders Schack-Mulligen
2025-05-16 11:46:22 +02:00
parent 13c5906e7e
commit db01828717
34 changed files with 142 additions and 102 deletions

View File

@@ -10,7 +10,7 @@ private import SemanticExprSpecific::SemanticExprConfig as Specific
*/ */
class SemBasicBlock extends Specific::BasicBlock { class SemBasicBlock extends Specific::BasicBlock {
/** Holds if this block (transitively) dominates `otherblock`. */ /** Holds if this block (transitively) dominates `otherblock`. */
final predicate bbDominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) } final predicate dominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) }
/** Gets an expression that is evaluated in this basic block. */ /** Gets an expression that is evaluated in this basic block. */
final SemExpr getAnExpr() { result.getBasicBlock() = this } final SemExpr getAnExpr() { result.getBasicBlock() = this }

View File

@@ -79,23 +79,47 @@ class BasicBlock extends BbImpl::BasicBlock {
/** Gets the immediately enclosing callable whose body contains this node. */ /** Gets the immediately enclosing callable whose body contains this node. */
Callable getEnclosingCallable() { result = this.getScope() } Callable getEnclosingCallable() { result = this.getScope() }
/** Gets an immediate successor of this basic block. */ /**
BasicBlock getABBSuccessor() { result = this.getASuccessor() } * DEPRECATED: Use `getASuccessor` instead.
*
* Gets an immediate successor of this basic block.
*/
deprecated BasicBlock getABBSuccessor() { result = this.getASuccessor() }
/** Gets an immediate predecessor of this basic block. */ /**
BasicBlock getABBPredecessor() { result.getABBSuccessor() = this } * DEPRECATED: Use `getAPredecessor` instead.
*
* Gets an immediate predecessor of this basic block.
*/
deprecated BasicBlock getABBPredecessor() { result.getASuccessor() = this }
/** Holds if this basic block strictly dominates `node`. */ /**
predicate bbStrictlyDominates(BasicBlock node) { this.strictlyDominates(node) } * DEPRECATED: Use `strictlyDominates` instead.
*
* Holds if this basic block strictly dominates `node`.
*/
deprecated predicate bbStrictlyDominates(BasicBlock node) { this.strictlyDominates(node) }
/** Holds if this basic block dominates `node`. (This is reflexive.) */ /**
predicate bbDominates(BasicBlock node) { this.dominates(node) } * DEPRECATED: Use `dominates` instead.
*
* Holds if this basic block dominates `node`. (This is reflexive.)
*/
deprecated predicate bbDominates(BasicBlock node) { this.dominates(node) }
/** Holds if this basic block strictly post-dominates `node`. */ /**
predicate bbStrictlyPostDominates(BasicBlock node) { this.strictlyPostDominates(node) } * DEPRECATED: Use `strictlyPostDominates` instead.
*
* Holds if this basic block strictly post-dominates `node`.
*/
deprecated predicate bbStrictlyPostDominates(BasicBlock node) { this.strictlyPostDominates(node) }
/** Holds if this basic block post-dominates `node`. (This is reflexive.) */ /**
predicate bbPostDominates(BasicBlock node) { this.postDominates(node) } * DEPRECATED: Use `postDominates` instead.
*
* Holds if this basic block post-dominates `node`. (This is reflexive.)
*/
deprecated predicate bbPostDominates(BasicBlock node) { this.postDominates(node) }
} }
/** A basic block that ends in an exit node. */ /** A basic block that ends in an exit node. */

View File

@@ -8,51 +8,72 @@ import java
* Predicates for basic-block-level dominance. * Predicates for basic-block-level dominance.
*/ */
/** The immediate dominance relation for basic blocks. */ /**
predicate bbIDominates(BasicBlock dom, BasicBlock node) { dom.immediatelyDominates(node) } * DEPRECATED: Use `BasicBlock::immediatelyDominates` instead.
*
* The immediate dominance relation for basic blocks.
*/
deprecated predicate bbIDominates(BasicBlock dom, BasicBlock node) {
dom.immediatelyDominates(node)
}
/** Exit points for basic-block control-flow. */ /** Exit points for basic-block control-flow. */
private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode } private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode }
/** Reversed `bbSucc`. */ /** Reversed `bbSucc`. */
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getABBSuccessor() } private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getASuccessor() }
/** The immediate post-dominance relation on basic blocks. */ /** The immediate post-dominance relation on basic blocks. */
cached deprecated predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
idominance(bbSink/1, bbPred/2)(_, dominator, node) idominance(bbSink/1, bbPred/2)(_, dominator, node)
/** Holds if `dom` strictly dominates `node`. */ /**
predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) { bbIDominates+(dom, node) } * DEPRECATED: Use `BasicBlock::strictlyDominates` instead.
*
/** Holds if `dom` dominates `node`. (This is reflexive.) */ * Holds if `dom` strictly dominates `node`.
predicate bbDominates(BasicBlock dom, BasicBlock node) { */
bbStrictlyDominates(dom, node) or dom = node deprecated predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) {
dom.strictlyDominates(node)
} }
/** Holds if `dom` strictly post-dominates `node`. */ /**
predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) { bbIPostDominates+(dom, node) } * DEPRECATED: Use `BasicBlock::dominates` instead.
*
* Holds if `dom` dominates `node`. (This is reflexive.)
*/
deprecated predicate bbDominates(BasicBlock dom, BasicBlock node) { dom.dominates(node) }
/** Holds if `dom` post-dominates `node`. (This is reflexive.) */ /**
predicate bbPostDominates(BasicBlock dom, BasicBlock node) { * DEPRECATED: Use `BasicBlock::strictlyPostDominates` instead.
bbStrictlyPostDominates(dom, node) or dom = node *
* Holds if `dom` strictly post-dominates `node`.
*/
deprecated predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) {
dom.strictlyPostDominates(node)
} }
/**
* DEPRECATED: Use `BasicBlock::postDominates` instead.
*
* Holds if `dom` post-dominates `node`. (This is reflexive.)
*/
deprecated predicate bbPostDominates(BasicBlock dom, BasicBlock node) { dom.postDominates(node) }
/** /**
* The dominance frontier relation for basic blocks. * The dominance frontier relation for basic blocks.
* *
* This is equivalent to: * This is equivalent to:
* *
* ``` * ```
* bbDominates(x, w.getABBPredecessor()) and not bbStrictlyDominates(x, w) * x.dominates(w.getAPredecessor()) and not x.strictlyDominates(w)
* ``` * ```
*/ */
predicate dominanceFrontier(BasicBlock x, BasicBlock w) { predicate dominanceFrontier(BasicBlock x, BasicBlock w) {
x = w.getABBPredecessor() and not bbIDominates(x, w) x = w.getAPredecessor() and not x.immediatelyDominates(w)
or or
exists(BasicBlock prev | dominanceFrontier(prev, w) | exists(BasicBlock prev | dominanceFrontier(prev, w) |
bbIDominates(x, prev) and x.immediatelyDominates(prev) and
not bbIDominates(x, w) not x.immediatelyDominates(w)
) )
} }
@@ -65,7 +86,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
exists(BasicBlock bb, int i | dominator = bb.getNode(i) and node = bb.getNode(i + 1)) exists(BasicBlock bb, int i | dominator = bb.getNode(i) and node = bb.getNode(i + 1))
or or
exists(BasicBlock dom, BasicBlock bb | exists(BasicBlock dom, BasicBlock bb |
bbIDominates(dom, bb) and dom.immediatelyDominates(bb) and
dominator = dom.getLastNode() and dominator = dom.getLastNode() and
node = bb.getFirstNode() node = bb.getFirstNode()
) )
@@ -75,7 +96,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
pragma[inline] pragma[inline]
predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) { predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined. // This predicate is gigantic, so it must be inlined.
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock()) dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
or or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i < j) exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i < j)
} }
@@ -84,7 +105,7 @@ predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
pragma[inline] pragma[inline]
predicate dominates(ControlFlowNode dom, ControlFlowNode node) { predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined. // This predicate is gigantic, so it must be inlined.
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock()) dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
or or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i <= j) exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i <= j)
} }
@@ -93,7 +114,7 @@ predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
pragma[inline] pragma[inline]
predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) { predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined. // This predicate is gigantic, so it must be inlined.
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock()) dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
or or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i > j) exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i > j)
} }
@@ -102,7 +123,7 @@ predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
pragma[inline] pragma[inline]
predicate postDominates(ControlFlowNode dom, ControlFlowNode node) { predicate postDominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined. // This predicate is gigantic, so it must be inlined.
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock()) dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
or or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i >= j) exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i >= j)
} }

View File

@@ -68,7 +68,7 @@ class ConditionBlock extends BasicBlock {
exists(BasicBlock succ | exists(BasicBlock succ |
succ = this.getTestSuccessor(testIsTrue) and succ = this.getTestSuccessor(testIsTrue) and
dominatingEdge(this, succ) and dominatingEdge(this, succ) and
succ.bbDominates(controlled) succ.dominates(controlled)
) )
} }
} }
@@ -287,7 +287,7 @@ private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
// Pattern cases are handled as condition blocks // Pattern cases are handled as condition blocks
not sc instanceof PatternCase and not sc instanceof PatternCase and
caseblock.getFirstNode() = sc.getControlFlowNode() and caseblock.getFirstNode() = sc.getControlFlowNode() and
caseblock.bbDominates(bb) and caseblock.dominates(bb) and
// Check we can't fall through from a previous block: // Check we can't fall through from a previous block:
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() | forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
isNonFallThroughPredecessor(sc, pred) isNonFallThroughPredecessor(sc, pred)
@@ -307,7 +307,7 @@ private predicate preconditionControls(MethodCall ma, BasicBlock controlled, boo
exists(BasicBlock check, BasicBlock succ | exists(BasicBlock check, BasicBlock succ |
preconditionBranchEdge(ma, check, succ, branch) and preconditionBranchEdge(ma, check, succ, branch) and
dominatingEdge(check, succ) and dominatingEdge(check, succ) and
succ.bbDominates(controlled) succ.dominates(controlled)
) )
} }

View File

@@ -47,7 +47,7 @@ private predicate callAlwaysPerformsAction(Call call, ActionConfiguration conf)
private predicate actionDominatesExit(Callable callable, ActionConfiguration conf) { private predicate actionDominatesExit(Callable callable, ActionConfiguration conf) {
exists(ExitBlock exit | exists(ExitBlock exit |
exit.getEnclosingCallable() = callable and exit.getEnclosingCallable() = callable and
actionBlock(conf).bbDominates(exit) actionBlock(conf).dominates(exit)
) )
} }
@@ -56,12 +56,12 @@ private BasicBlock nonDominatingActionBlock(ActionConfiguration conf) {
exists(ExitBlock exit | exists(ExitBlock exit |
result = actionBlock(conf) and result = actionBlock(conf) and
exit.getEnclosingCallable() = result.getEnclosingCallable() and exit.getEnclosingCallable() = result.getEnclosingCallable() and
not result.bbDominates(exit) not result.dominates(exit)
) )
} }
private class JoinBlock extends BasicBlock { private class JoinBlock extends BasicBlock {
JoinBlock() { 2 <= strictcount(this.getABBPredecessor()) } JoinBlock() { 2 <= strictcount(this.getAPredecessor()) }
} }
/** /**
@@ -72,8 +72,8 @@ private predicate postActionBlock(BasicBlock bb, ActionConfiguration conf) {
bb = nonDominatingActionBlock(conf) bb = nonDominatingActionBlock(conf)
or or
if bb instanceof JoinBlock if bb instanceof JoinBlock
then forall(BasicBlock pred | pred = bb.getABBPredecessor() | postActionBlock(pred, conf)) then forall(BasicBlock pred | pred = bb.getAPredecessor() | postActionBlock(pred, conf))
else postActionBlock(bb.getABBPredecessor(), conf) else postActionBlock(bb.getAPredecessor(), conf)
} }
/** Holds if every path through `callable` goes through at least one action node. */ /** Holds if every path through `callable` goes through at least one action node. */

View File

@@ -209,7 +209,7 @@ class UnreachableBasicBlock extends BasicBlock {
or or
// This block is not reachable in the CFG, and is not the entrypoint in a callable, an // This block is not reachable in the CFG, and is not the entrypoint in a callable, an
// expression in an assert statement, or a catch clause. // expression in an assert statement, or a catch clause.
forall(BasicBlock bb | bb = this.getABBPredecessor() | bb instanceof UnreachableBasicBlock) and forall(BasicBlock bb | bb = this.getAPredecessor() | bb instanceof UnreachableBasicBlock) and
not exists(Callable c | c.getBody().getControlFlowNode() = this.getFirstNode()) and not exists(Callable c | c.getBody().getControlFlowNode() = this.getFirstNode()) and
not this.getFirstNode().asExpr().getEnclosingStmt() instanceof AssertStmt and not this.getFirstNode().asExpr().getEnclosingStmt() instanceof AssertStmt and
not this.getFirstNode().asStmt() instanceof CatchClause not this.getFirstNode().asStmt() instanceof CatchClause
@@ -219,11 +219,10 @@ class UnreachableBasicBlock extends BasicBlock {
// Not accessible from the switch expression // Not accessible from the switch expression
unreachableCaseBlock = constSwitchStmt.getAFailingCase().getBasicBlock() and unreachableCaseBlock = constSwitchStmt.getAFailingCase().getBasicBlock() and
// Not accessible from the successful case // Not accessible from the successful case
not constSwitchStmt.getMatchingCase().getBasicBlock().getABBSuccessor*() = not constSwitchStmt.getMatchingCase().getBasicBlock().getASuccessor*() = unreachableCaseBlock
unreachableCaseBlock
| |
// Blocks dominated by an unreachable case block are unreachable // Blocks dominated by an unreachable case block are unreachable
unreachableCaseBlock.bbDominates(this) unreachableCaseBlock.dominates(this)
) )
} }
} }

View File

@@ -239,7 +239,7 @@ SsaVariable getADefinition(SsaVariable v, boolean fromBackEdge) {
exists(SsaVariable inp, BasicBlock bb, boolean fbe | exists(SsaVariable inp, BasicBlock bb, boolean fbe |
v.(SsaPhiNode).hasInputFromBlock(inp, bb) and v.(SsaPhiNode).hasInputFromBlock(inp, bb) and
result = getADefinition(inp, fbe) and result = getADefinition(inp, fbe) and
(if v.getBasicBlock().bbDominates(bb) then fromBackEdge = true else fromBackEdge = fbe) (if v.getBasicBlock().dominates(bb) then fromBackEdge = true else fromBackEdge = fbe)
) )
} }
@@ -306,7 +306,7 @@ private predicate guardControlsPhiBranch(
guard.directlyControls(upd.getBasicBlock(), branch) and guard.directlyControls(upd.getBasicBlock(), branch) and
upd.getDefiningExpr().(VariableAssign).getSource() = e and upd.getDefiningExpr().(VariableAssign).getSource() = e and
upd = phi.getAPhiInput() and upd = phi.getAPhiInput() and
guard.getBasicBlock().bbStrictlyDominates(phi.getBasicBlock()) guard.getBasicBlock().strictlyDominates(phi.getBasicBlock())
} }
/** /**
@@ -331,7 +331,7 @@ private predicate conditionalAssign(SsaVariable v, Guard guard, boolean branch,
forall(SsaVariable other | other != upd and other = phi.getAPhiInput() | forall(SsaVariable other | other != upd and other = phi.getAPhiInput() |
guard.directlyControls(other.getBasicBlock(), branch.booleanNot()) guard.directlyControls(other.getBasicBlock(), branch.booleanNot())
or or
other.getBasicBlock().bbDominates(guard.getBasicBlock()) and other.getBasicBlock().dominates(guard.getBasicBlock()) and
not other.isLiveAtEndOfBlock(getAGuardBranchSuccessor(guard, branch)) not other.isLiveAtEndOfBlock(getAGuardBranchSuccessor(guard, branch))
) )
) )

View File

@@ -298,7 +298,7 @@ private predicate impossibleEdge(BasicBlock bb1, BasicBlock bb2) {
private predicate leavingFinally(BasicBlock bb1, BasicBlock bb2, boolean normaledge) { private predicate leavingFinally(BasicBlock bb1, BasicBlock bb2, boolean normaledge) {
exists(TryStmt try, BlockStmt finally | exists(TryStmt try, BlockStmt finally |
try.getFinally() = finally and try.getFinally() = finally and
bb1.getABBSuccessor() = bb2 and bb1.getASuccessor() = bb2 and
bb1.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and bb1.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and
not bb2.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and not bb2.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and
if bb1.getLastNode().getANormalSuccessor() = bb2.getFirstNode() if bb1.getLastNode().getANormalSuccessor() = bb2.getFirstNode()
@@ -339,7 +339,7 @@ private predicate nullVarStep(
midssa.isLiveAtEndOfBlock(mid) and midssa.isLiveAtEndOfBlock(mid) and
not ensureNotNull(midssa).getBasicBlock() = mid and not ensureNotNull(midssa).getBasicBlock() = mid and
not assertFail(mid, _) and not assertFail(mid, _) and
bb = mid.getABBSuccessor() and bb = mid.getASuccessor() and
not impossibleEdge(mid, bb) and not impossibleEdge(mid, bb) and
not exists(boolean branch | nullGuard(midssa, branch, false).hasBranchEdge(mid, bb, branch)) and not exists(boolean branch | nullGuard(midssa, branch, false).hasBranchEdge(mid, bb, branch)) and
not (leavingFinally(mid, bb, true) and midstoredcompletion = true) and not (leavingFinally(mid, bb, true) and midstoredcompletion = true) and

View File

@@ -209,7 +209,7 @@ module Sem implements Semantic<Location> {
class BasicBlock = J::BasicBlock; class BasicBlock = J::BasicBlock;
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() } BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
private predicate id(ExprParent x, ExprParent y) { x = y } private predicate id(ExprParent x, ExprParent y) { x = y }

View File

@@ -321,14 +321,14 @@ private module Input implements TypeFlowInput<Location> {
*/ */
private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, BaseSsaVariable v) { private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, BaseSsaVariable v) {
ioe.getExpr() = v.getAUse() and ioe.getExpr() = v.getAUse() and
strictcount(bb.getABBPredecessor()) > 1 and strictcount(bb.getAPredecessor()) > 1 and
exists(ConditionBlock cb | cb.getCondition() = ioe and cb.getTestSuccessor(true) = bb) exists(ConditionBlock cb | cb.getCondition() = ioe and cb.getTestSuccessor(true) = bb)
} }
/** Holds if `bb` is disjunctively guarded by multiple `instanceof` tests on `v`. */ /** Holds if `bb` is disjunctively guarded by multiple `instanceof` tests on `v`. */
private predicate instanceofDisjunction(BasicBlock bb, BaseSsaVariable v) { private predicate instanceofDisjunction(BasicBlock bb, BaseSsaVariable v) {
strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) = strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) =
strictcount(bb.getABBPredecessor()) strictcount(bb.getAPredecessor())
} }
/** /**
@@ -338,7 +338,7 @@ private module Input implements TypeFlowInput<Location> {
predicate instanceofDisjunctionGuarded(TypeFlowNode n, RefType t) { predicate instanceofDisjunctionGuarded(TypeFlowNode n, RefType t) {
exists(BasicBlock bb, InstanceOfExpr ioe, BaseSsaVariable v, VarAccess va | exists(BasicBlock bb, InstanceOfExpr ioe, BaseSsaVariable v, VarAccess va |
instanceofDisjunction(bb, v) and instanceofDisjunction(bb, v) and
bb.bbDominates(va.getBasicBlock()) and bb.dominates(va.getBasicBlock()) and
va = v.getAUse() and va = v.getAUse() and
instanceofDisjunct(ioe, bb, v) and instanceofDisjunct(ioe, bb, v) and
t = ioe.getSyntacticCheckedType() and t = ioe.getSyntacticCheckedType() and

View File

@@ -157,15 +157,14 @@ private import BaseSsaImpl
private module SsaInput implements SsaImplCommon::InputSig<Location> { private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import java as J private import java as J
private import semmle.code.java.controlflow.Dominance as Dom
class BasicBlock = J::BasicBlock; class BasicBlock = J::BasicBlock;
class ControlFlowNode = J::ControlFlowNode; class ControlFlowNode = J::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { Dom::bbIDominates(result, bb) } BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() } BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class SourceVariable = BaseSsaSourceVariable; class SourceVariable = BaseSsaSourceVariable;

View File

@@ -83,12 +83,12 @@ private module CaptureInput implements VariableCapture::InputSig<Location> {
class ControlFlowNode = J::ControlFlowNode; class ControlFlowNode = J::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { bbIDominates(result, bb) } BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result.(J::BasicBlock).immediatelyDominates(bb)
BasicBlock getABasicBlockSuccessor(BasicBlock bb) {
result = bb.(J::BasicBlock).getABBSuccessor()
} }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.(J::BasicBlock).getASuccessor() }
//TODO: support capture of `this` in lambdas //TODO: support capture of `this` in lambdas
class CapturedVariable instanceof LocalScopeVariable { class CapturedVariable instanceof LocalScopeVariable {
CapturedVariable() { CapturedVariable() {

View File

@@ -40,14 +40,14 @@ private module ThisFlow {
private int lastRank(BasicBlock b) { result = max(int rankix | thisRank(_, b, rankix)) } private int lastRank(BasicBlock b) { result = max(int rankix | thisRank(_, b, rankix)) }
private predicate blockPrecedesThisAccess(BasicBlock b) { thisAccess(_, b.getABBSuccessor*(), _) } private predicate blockPrecedesThisAccess(BasicBlock b) { thisAccess(_, b.getASuccessor*(), _) }
private predicate thisAccessBlockReaches(BasicBlock b1, BasicBlock b2) { private predicate thisAccessBlockReaches(BasicBlock b1, BasicBlock b2) {
thisAccess(_, b1, _) and b2 = b1.getABBSuccessor() thisAccess(_, b1, _) and b2 = b1.getASuccessor()
or or
exists(BasicBlock mid | exists(BasicBlock mid |
thisAccessBlockReaches(b1, mid) and thisAccessBlockReaches(b1, mid) and
b2 = mid.getABBSuccessor() and b2 = mid.getASuccessor() and
not thisAccess(_, mid, _) and not thisAccess(_, mid, _) and
blockPrecedesThisAccess(b2) blockPrecedesThisAccess(b2)
) )

View File

@@ -165,15 +165,14 @@ private predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, Basic
private module SsaInput implements SsaImplCommon::InputSig<Location> { private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import java as J private import java as J
private import semmle.code.java.controlflow.Dominance as Dom
class BasicBlock = J::BasicBlock; class BasicBlock = J::BasicBlock;
class ControlFlowNode = J::ControlFlowNode; class ControlFlowNode = J::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { Dom::bbIDominates(result, bb) } BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() } BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class SourceVariable = SsaSourceVariable; class SourceVariable = SsaSourceVariable;

View File

@@ -24,6 +24,6 @@ private class SslProceedCall extends MethodCall {
/** Holds if `m` trusts all certificates by calling `SslErrorHandler.proceed` unconditionally. */ /** Holds if `m` trusts all certificates by calling `SslErrorHandler.proceed` unconditionally. */
predicate trustsAllCerts(OnReceivedSslErrorMethod m) { predicate trustsAllCerts(OnReceivedSslErrorMethod m) {
exists(SslProceedCall pr | pr.getQualifier().(VarAccess).getVariable() = m.handlerArg() | exists(SslProceedCall pr | pr.getQualifier().(VarAccess).getVariable() = m.handlerArg() |
pr.getBasicBlock().bbPostDominates(m.getBody().getBasicBlock()) pr.getBasicBlock().postDominates(m.getBody().getBasicBlock())
) )
} }

View File

@@ -21,7 +21,7 @@ private module ValidationMethod<DataFlow::guardChecksSig/3 validationGuard> {
validationMethod(ma.getMethod(), pos) and validationMethod(ma.getMethod(), pos) and
ma.getArgument(pos) = rv and ma.getArgument(pos) = rv and
adjacentUseUseSameVar(rv, result.asExpr()) and adjacentUseUseSameVar(rv, result.asExpr()) and
ma.getBasicBlock().bbDominates(result.asExpr().getBasicBlock()) ma.getBasicBlock().dominates(result.asExpr().getBasicBlock())
) )
} }

View File

@@ -168,7 +168,7 @@ private class FullyDecodesUrlBarrier extends DataFlow::Node {
exists(Variable v, Expr e | this.asExpr() = v.getAnAccess() | exists(Variable v, Expr e | this.asExpr() = v.getAnAccess() |
fullyDecodesUrlGuard(e) and fullyDecodesUrlGuard(e) and
e = v.getAnAccess() and e = v.getAnAccess() and
e.getBasicBlock().bbDominates(this.asExpr().getBasicBlock()) e.getBasicBlock().dominates(this.asExpr().getBasicBlock())
) )
} }
} }

View File

@@ -42,14 +42,14 @@ private predicate validatedAccess(VarAccess va) {
exists(BasicBlock succ | exists(BasicBlock succ |
succ.getFirstNode() = node.getANormalSuccessor() and succ.getFirstNode() = node.getANormalSuccessor() and
dominatingEdge(node.getBasicBlock(), succ) and dominatingEdge(node.getBasicBlock(), succ) and
succ.bbDominates(va.getBasicBlock()) succ.dominates(va.getBasicBlock())
) )
or or
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
bb.getNode(i) = node and bb.getNode(i) = node and
bb.getNode(i + 1) = node.getANormalSuccessor() bb.getNode(i + 1) = node.getANormalSuccessor()
| |
bb.bbStrictlyDominates(va.getBasicBlock()) or bb.strictlyDominates(va.getBasicBlock()) or
bb.getNode(any(int j | j > i)).asExpr() = va bb.getNode(any(int j | j > i)).asExpr() = va
) )
) )

View File

@@ -145,9 +145,7 @@ predicate variableLockStateCheck(LockType t, BasicBlock checkblock, BasicBlock f
predicate blockIsLocked(LockType t, BasicBlock src, BasicBlock b, int locks) { predicate blockIsLocked(LockType t, BasicBlock src, BasicBlock b, int locks) {
lockUnlockBlock(t, b, locks) and src = b and locks > 0 lockUnlockBlock(t, b, locks) and src = b and locks > 0
or or
exists(BasicBlock pred, int predlocks, int curlocks, int failedlock | exists(BasicBlock pred, int predlocks, int curlocks, int failedlock | pred = b.getAPredecessor() |
pred = b.getABBPredecessor()
|
// The number of net locks from the `src` block to the predecessor block `pred` is `predlocks`. // The number of net locks from the `src` block to the predecessor block `pred` is `predlocks`.
blockIsLocked(t, src, pred, predlocks) and blockIsLocked(t, src, pred, predlocks) and
// The recursive call ensures that at least one lock is held, so do not consider the false // The recursive call ensures that at least one lock is held, so do not consider the false

View File

@@ -18,6 +18,6 @@ where
iteration = inner.getAnIterationVariable() and iteration = inner.getAnIterationVariable() and
iteration = outer.getAnIterationVariable() and iteration = outer.getAnIterationVariable() and
inner.getEnclosingStmt+() = outer and inner.getEnclosingStmt+() = outer and
inner.getBasicBlock().getABBSuccessor+() = outer.getCondition().getBasicBlock() inner.getBasicBlock().getASuccessor+() = outer.getCondition().getBasicBlock()
select inner.getCondition(), "Nested for statement uses loop variable $@ of enclosing $@.", select inner.getCondition(), "Nested for statement uses loop variable $@ of enclosing $@.",
iteration, iteration.getName(), outer, "for statement" iteration, iteration.getName(), outer, "for statement"

View File

@@ -37,7 +37,7 @@ predicate overwritten(VariableUpdate upd) {
bb1.getNode(i) = upd.getControlFlowNode() and bb1.getNode(i) = upd.getControlFlowNode() and
bb2.getNode(j) = overwrite.getControlFlowNode() bb2.getNode(j) = overwrite.getControlFlowNode()
| |
bb1.getABBSuccessor+() = bb2 bb1.getASuccessor+() = bb2
or or
bb1 = bb2 and i < j bb1 = bb2 and i < j
) )

View File

@@ -14,7 +14,7 @@ private predicate blockInSwitch(SwitchStmt s, BasicBlock b) {
private predicate switchCaseControlFlow(SwitchStmt switch, BasicBlock b1, BasicBlock b2) { private predicate switchCaseControlFlow(SwitchStmt switch, BasicBlock b1, BasicBlock b2) {
blockInSwitch(switch, b1) and blockInSwitch(switch, b1) and
b1.getABBSuccessor() = b2 and b1.getASuccessor() = b2 and
blockInSwitch(switch, b2) blockInSwitch(switch, b2)
} }

View File

@@ -13,7 +13,7 @@ import semmle.code.java.dataflow.SSA
class SsaConvertibleReadAccess extends VarRead { class SsaConvertibleReadAccess extends VarRead {
SsaConvertibleReadAccess() { SsaConvertibleReadAccess() {
this.getEnclosingCallable().getBody().getBasicBlock().getABBSuccessor*() = this.getBasicBlock() and this.getEnclosingCallable().getBody().getBasicBlock().getASuccessor*() = this.getBasicBlock() and
( (
not exists(this.getQualifier()) not exists(this.getQualifier())
or or

View File

@@ -1,6 +1,6 @@
import default import java
import semmle.code.java.controlflow.Dominance import semmle.code.java.controlflow.Dominance
from BasicBlock b, BasicBlock b2 from BasicBlock b, BasicBlock b2
where bbStrictlyDominates(b, b2) where b.strictlyDominates(b2)
select b, b2 select b, b2

View File

@@ -1,5 +1,5 @@
import default import java
from BasicBlock b, BasicBlock b2 from BasicBlock b, BasicBlock b2
where b.getABBSuccessor() = b2 where b.getASuccessor() = b2
select b, b2 select b, b2

View File

@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
from Callable c, ControlFlowNode dom, ControlFlowNode node from Callable c, ControlFlowNode dom, ControlFlowNode node
where where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and strictlyDominates(dom, node) and
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node) dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
select c, dom, node select c, dom, node

View File

@@ -1,6 +1,6 @@
import default import java
import semmle.code.java.controlflow.Dominance import semmle.code.java.controlflow.Dominance
from BasicBlock b, BasicBlock b2 from BasicBlock b, BasicBlock b2
where bbStrictlyDominates(b, b2) where b.strictlyDominates(b2)
select b, b2 select b, b2

View File

@@ -1,5 +1,5 @@
import default import java
from BasicBlock b, BasicBlock b2 from BasicBlock b, BasicBlock b2
where b.getABBSuccessor() = b2 where b.getASuccessor() = b2
select b, b2 select b, b2

View File

@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
from Callable c, ControlFlowNode dom, ControlFlowNode node from Callable c, ControlFlowNode dom, ControlFlowNode node
where where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and strictlyDominates(dom, node) and
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node) dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
select c, dom, node select c, dom, node

View File

@@ -1,6 +1,6 @@
import default import java
import semmle.code.java.controlflow.Dominance import semmle.code.java.controlflow.Dominance
from BasicBlock b, BasicBlock b2 from BasicBlock b, BasicBlock b2
where bbStrictlyDominates(b, b2) where b.strictlyDominates(b2)
select b, b2 select b, b2

View File

@@ -1,5 +1,5 @@
import default import java
from BasicBlock b, BasicBlock b2 from BasicBlock b, BasicBlock b2
where b.getABBSuccessor() = b2 where b.getASuccessor() = b2
select b, b2 select b, b2

View File

@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
from Callable c, ControlFlowNode dom, ControlFlowNode node from Callable c, ControlFlowNode dom, ControlFlowNode node
where where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and strictlyDominates(dom, node) and
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node) dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
select c, dom, node select c, dom, node

View File

@@ -146,7 +146,7 @@ signature module Semantic<LocationSig Location> {
class BasicBlock { class BasicBlock {
/** Holds if this block (transitively) dominates `otherblock`. */ /** Holds if this block (transitively) dominates `otherblock`. */
predicate bbDominates(BasicBlock otherBlock); predicate dominates(BasicBlock otherBlock);
} }
/** Gets an immediate successor of basic block `bb`, if any. */ /** Gets an immediate successor of basic block `bb`, if any. */

View File

@@ -205,7 +205,7 @@ module MakeUtils<LocationSig Location, Semantic<Location> Lang, DeltaSig D> {
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge) { predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge) {
edge.phiInput(phi, inp) and edge.phiInput(phi, inp) and
( (
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or phi.getBasicBlock().dominates(edge.getOrigBlock()) or
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock()) irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock())
) )
} }
@@ -227,7 +227,7 @@ module MakeUtils<LocationSig Location, Semantic<Location> Lang, DeltaSig D> {
private predicate trimmedEdge(BasicBlock pred, BasicBlock succ) { private predicate trimmedEdge(BasicBlock pred, BasicBlock succ) {
getABasicBlockSuccessor(pred) = succ and getABasicBlockSuccessor(pred) = succ and
not succ.bbDominates(pred) not succ.dominates(pred)
} }
/** /**