mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Java/C++: Move range util backEdge predicate to shared pack.
This commit is contained in:
@@ -12,9 +12,6 @@ class SemBasicBlock extends Specific::BasicBlock {
|
||||
/** Holds if this block (transitively) dominates `otherblock`. */
|
||||
final predicate bbDominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) }
|
||||
|
||||
/** Holds if this block has dominance information. */
|
||||
final predicate hasDominanceInformation() { Specific::hasDominanceInformation(this) }
|
||||
|
||||
/** Gets an expression that is evaluated in this basic block. */
|
||||
final SemExpr getAnExpr() { result.getBasicBlock() = this }
|
||||
|
||||
|
||||
@@ -199,8 +199,6 @@ module SemanticExprConfig {
|
||||
dominator.dominates(dominated)
|
||||
}
|
||||
|
||||
predicate hasDominanceInformation(BasicBlock block) { any() }
|
||||
|
||||
private predicate id(Cpp::Locatable x, Cpp::Locatable y) { x = y }
|
||||
|
||||
private predicate idOf(Cpp::Locatable x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
|
||||
@@ -63,36 +63,3 @@ class SemSsaReadPositionBlock extends SemSsaReadPosition {
|
||||
|
||||
SemExpr getAnExpr() { result = this.getBlock().getAnExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along a back edge.
|
||||
*/
|
||||
predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge) {
|
||||
edge.phiInput(phi, inp) and
|
||||
// Conservatively assume that every edge is a back edge if we don't have dominance information.
|
||||
(
|
||||
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
|
||||
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock()) or
|
||||
not edge.getOrigBlock().hasDominanceInformation()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the edge from b1 to b2 is part of a multiple-entry cycle in an irreducible control flow
|
||||
* graph.
|
||||
*
|
||||
* An ireducible control flow graph is one where the usual dominance-based back edge detection does
|
||||
* not work, because there is a cycle with multiple entry points, meaning there are
|
||||
* mutually-reachable basic blocks where neither dominates the other. For such a graph, we first
|
||||
* remove all detectable back-edges using the normal condition that the predecessor block is
|
||||
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
|
||||
* edges.
|
||||
*/
|
||||
private predicate irreducibleSccEdge(SemBasicBlock b1, SemBasicBlock b2) {
|
||||
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
|
||||
}
|
||||
|
||||
private predicate trimmedEdge(SemBasicBlock pred, SemBasicBlock succ) {
|
||||
pred.getASuccessor() = succ and
|
||||
not succ.bbDominates(pred)
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ module Sem implements Semantic {
|
||||
|
||||
class BasicBlock = SemBasicBlock;
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
class Guard = SemGuard;
|
||||
|
||||
predicate implies_v2 = semImplies_v2/4;
|
||||
@@ -100,8 +102,6 @@ module Sem implements Semantic {
|
||||
|
||||
class SsaReadPositionBlock = SemSsaReadPositionBlock;
|
||||
|
||||
predicate backEdge = semBackEdge/3;
|
||||
|
||||
predicate conversionCannotOverflow(Type fromType, Type toType) {
|
||||
SemanticType::conversionCannotOverflow(fromType, toType)
|
||||
}
|
||||
|
||||
@@ -211,7 +211,11 @@ module Sem implements Semantic {
|
||||
|
||||
class BasicBlock = J::BasicBlock;
|
||||
|
||||
class Guard extends GL::Guard {
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
|
||||
|
||||
final private class FinalGuard = GL::Guard;
|
||||
|
||||
class Guard extends FinalGuard {
|
||||
Expr asExpr() { result = this }
|
||||
}
|
||||
|
||||
@@ -261,6 +265,8 @@ module Sem implements Semantic {
|
||||
|
||||
class SsaReadPositionPhiInputEdge extends SsaReadPosition instanceof SsaReadPos::SsaReadPositionPhiInputEdge
|
||||
{
|
||||
BasicBlock getOrigBlock() { result = super.getOrigBlock() }
|
||||
|
||||
predicate phiInput(SsaPhiNode phi, SsaVariable inp) { super.phiInput(phi, inp) }
|
||||
}
|
||||
|
||||
@@ -268,10 +274,6 @@ module Sem implements Semantic {
|
||||
BasicBlock getBlock() { result = super.getBlock() }
|
||||
}
|
||||
|
||||
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge) {
|
||||
RU::backEdge(phi, inp, edge)
|
||||
}
|
||||
|
||||
predicate conversionCannotOverflow = safeCast/2;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ private import SSA
|
||||
private import semmle.code.java.controlflow.internal.GuardsLogic
|
||||
private import semmle.code.java.dataflow.internal.rangeanalysis.SsaReadPositionCommon
|
||||
private import semmle.code.java.Constants
|
||||
private import semmle.code.java.dataflow.RangeAnalysis
|
||||
private import codeql.rangeanalysis.internal.RangeUtils
|
||||
|
||||
private predicate backEdge = MakeUtils<Sem, IntDelta>::backEdge/3;
|
||||
|
||||
/**
|
||||
* Holds if `v` is an input to `phi` that is not along a back edge, and the
|
||||
@@ -181,18 +185,6 @@ Expr ssaRead(SsaVariable v, int delta) {
|
||||
result.(AssignExpr).getSource() = ssaRead(v, delta)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along a back edge.
|
||||
*/
|
||||
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge) {
|
||||
edge.phiInput(phi, inp) and
|
||||
// Conservatively assume that every edge is a back edge if we don't have dominance information.
|
||||
(
|
||||
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
|
||||
not hasDominanceInformation(edge.getOrigBlock())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` directly controls the position `controlled` with the
|
||||
* value `testIsTrue`.
|
||||
|
||||
@@ -142,7 +142,13 @@ signature module Semantic {
|
||||
Expr getBranchExpr(boolean branch);
|
||||
}
|
||||
|
||||
class BasicBlock;
|
||||
class BasicBlock {
|
||||
/** Holds if this block (transitively) dominates `otherblock`. */
|
||||
predicate bbDominates(BasicBlock otherBlock);
|
||||
}
|
||||
|
||||
/** Gets an immediate successor of basic block `bb`, if any. */
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb);
|
||||
|
||||
class Guard {
|
||||
string toString();
|
||||
@@ -176,6 +182,8 @@ signature module Semantic {
|
||||
|
||||
class SsaVariable {
|
||||
Expr getAUse();
|
||||
|
||||
BasicBlock getBasicBlock();
|
||||
}
|
||||
|
||||
class SsaPhiNode extends SsaVariable;
|
||||
@@ -189,6 +197,8 @@ signature module Semantic {
|
||||
}
|
||||
|
||||
class SsaReadPositionPhiInputEdge extends SsaReadPosition {
|
||||
BasicBlock getOrigBlock();
|
||||
|
||||
predicate phiInput(SsaPhiNode phi, SsaVariable inp);
|
||||
}
|
||||
|
||||
@@ -196,8 +206,6 @@ signature module Semantic {
|
||||
BasicBlock getBlock();
|
||||
}
|
||||
|
||||
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge);
|
||||
|
||||
predicate conversionCannotOverflow(Type fromType, Type toType);
|
||||
}
|
||||
|
||||
@@ -928,7 +936,7 @@ module RangeStage<
|
||||
origdelta = D::fromFloat(0) and
|
||||
reason = TSemNoReason()
|
||||
|
|
||||
if Sem::backEdge(phi, inp, edge)
|
||||
if backEdge(phi, inp, edge)
|
||||
then
|
||||
fromBackEdge = true and
|
||||
(
|
||||
|
||||
@@ -34,4 +34,37 @@ module MakeUtils<Semantic Lang, DeltaSig D> {
|
||||
or
|
||||
result.(Lang::CopyValueExpr).getOperand() = ssaRead(v, delta)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along a back edge.
|
||||
*/
|
||||
predicate backEdge(
|
||||
Lang::SsaPhiNode phi, Lang::SsaVariable inp, Lang::SsaReadPositionPhiInputEdge edge
|
||||
) {
|
||||
edge.phiInput(phi, inp) and
|
||||
(
|
||||
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
|
||||
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the edge from b1 to b2 is part of a multiple-entry cycle in an irreducible control flow
|
||||
* graph. Or if the edge is part of a cycle in unreachable code.
|
||||
*
|
||||
* An irreducible control flow graph is one where the usual dominance-based back edge detection does
|
||||
* not work, because there is a cycle with multiple entry points, meaning there are
|
||||
* mutually-reachable basic blocks where neither dominates the other. For such a graph, we first
|
||||
* remove all detectable back-edges using the normal condition that the predecessor block is
|
||||
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
|
||||
* edges.
|
||||
*/
|
||||
private predicate irreducibleSccEdge(Lang::BasicBlock b1, Lang::BasicBlock b2) {
|
||||
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
|
||||
}
|
||||
|
||||
private predicate trimmedEdge(Lang::BasicBlock pred, Lang::BasicBlock succ) {
|
||||
Lang::getABasicBlockSuccessor(pred) = succ and
|
||||
not succ.bbDominates(pred)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user