diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index cb02791e96cc..e7dd817cecd9 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -180,7 +180,7 @@ class CompileTimeConstantExpr extends Expr { /** * Gets the string value of this expression, where possible. */ - pragma[nomagic] + cached string getStringValue() { result = this.(StringLiteral).getValue() or @@ -205,7 +205,7 @@ class CompileTimeConstantExpr extends Expr { /** * Gets the boolean value of this expression, where possible. */ - pragma[nomagic] + cached boolean getBooleanValue() { // Literal value. result = this.(BooleanLiteral).getBooleanValue() diff --git a/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll b/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll index 972f97ba3674..c2f9e8a6a697 100644 --- a/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll +++ b/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll @@ -5,6 +5,19 @@ import java import Dominance +cached +private module BasicBlockStage { + cached + predicate ref() { any() } + + cached + predicate backref() { + (exists(any(BasicBlock bb).getABBSuccessor()) implies any()) and + (exists(any(BasicBlock bb).getNode(_)) implies any()) and + (exists(any(BasicBlock bb).length()) implies any()) + } +} + /** * A control-flow node that represents the start of a basic block. * @@ -12,8 +25,11 @@ import Dominance * often be treated as a unit in analyses. */ class BasicBlock extends ControlFlowNode { + cached BasicBlock() { - not exists(this.getAPredecessor()) and exists(this.getASuccessor()) + BasicBlockStage::ref() and + not exists(this.getAPredecessor()) and + exists(this.getASuccessor()) or strictcount(this.getAPredecessor()) > 1 or @@ -24,7 +40,10 @@ class BasicBlock extends ControlFlowNode { /** Gets an immediate successor of this basic block. */ cached - BasicBlock getABBSuccessor() { result = this.getLastNode().getASuccessor() } + BasicBlock getABBSuccessor() { + BasicBlockStage::ref() and + result = this.getLastNode().getASuccessor() + } /** Gets an immediate predecessor of this basic block. */ BasicBlock getABBPredecessor() { result.getABBSuccessor() = this } @@ -35,7 +54,9 @@ class BasicBlock extends ControlFlowNode { /** Gets the control-flow node at a specific (zero-indexed) position in this basic block. */ cached ControlFlowNode getNode(int pos) { - result = this and pos = 0 + BasicBlockStage::ref() and + result = this and + pos = 0 or exists(ControlFlowNode mid, int mid_pos | pos = mid_pos + 1 | this.getNode(mid_pos) = mid and @@ -52,7 +73,10 @@ class BasicBlock extends ControlFlowNode { /** Gets the number of control-flow nodes contained in this basic block. */ cached - int length() { result = strictcount(this.getANode()) } + int length() { + BasicBlockStage::ref() and + result = strictcount(this.getANode()) + } /** Holds if this basic block strictly dominates `node`. */ predicate bbStrictlyDominates(BasicBlock node) { bbStrictlyDominates(this, node) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll index 1b912f919756..eeac19e66a74 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll @@ -14,9 +14,26 @@ import java private import codeql.ssa.Ssa as SsaImplCommon +cached +private module BaseSsaStage { + cached + predicate ref() { any() } + + cached + predicate backref() { + (exists(TLocalVar(_, _)) implies any()) and + (exists(any(BaseSsaSourceVariable v).getAnAccess()) implies any()) and + (exists(getAUse(_)) implies any()) + } +} + +cached private newtype TBaseSsaSourceVariable = TLocalVar(Callable c, LocalScopeVariable v) { - c = v.getCallable() or c = v.getAnAccess().getEnclosingCallable() + BaseSsaStage::ref() and + c = v.getCallable() + or + c = v.getAnAccess().getEnclosingCallable() } /** @@ -31,6 +48,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable { */ cached VarAccess getAnAccess() { + BaseSsaStage::ref() and exists(LocalScopeVariable v, Callable c | this = TLocalVar(c, v) and result = v.getAnAccess() and result.getEnclosingCallable() = c ) @@ -188,6 +206,7 @@ cached private module Cached { cached VarRead getAUse(Impl::Definition def) { + BaseSsaStage::ref() and exists(BaseSsaSourceVariable v, BasicBlock bb, int i | Impl::ssaDefReachesRead(v, def, bb, i) and result.getControlFlowNode() = bb.getNode(i) and diff --git a/java/ql/lib/semmle/code/java/environment/SystemProperty.qll b/java/ql/lib/semmle/code/java/environment/SystemProperty.qll index 63ded626c115..bee91d7c6b7f 100644 --- a/java/ql/lib/semmle/code/java/environment/SystemProperty.qll +++ b/java/ql/lib/semmle/code/java/environment/SystemProperty.qll @@ -269,18 +269,24 @@ private MethodCall getSystemPropertyFromSpringProperties(string propertyName) { * for final variables. */ private predicate localExprFlowPlusInitializers(Expr e1, Expr e2) { + e1 = e2 or localFlowPlusInitializers(DataFlow::exprNode(e1), DataFlow::exprNode(e2)) } +private predicate localFlowPlusInitializers(DataFlow::Node pred, DataFlow::Node succ) = + fastTC(localFlowStepPlusInitializers/2)(pred, succ) + /** - * Holds if data can flow from `pred` to `succ` in zero or more - * local (intra-procedural) steps or via instance or static variable intializers + * Holds if data can flow from `pred` to `succ` in a + * local (intra-procedural) step or via instance or static variable intializers * for final variables. */ -private predicate localFlowPlusInitializers(DataFlow::Node pred, DataFlow::Node succ) { - exists(Variable v | v.isFinal() and pred.asExpr() = v.getInitializer() | - DataFlow::localFlow(DataFlow::exprNode(v.getAnAccess()), succ) +private predicate localFlowStepPlusInitializers(DataFlow::Node pred, DataFlow::Node succ) { + exists(Variable v | + v.isFinal() and + pred.asExpr() = v.getInitializer() and + succ.asExpr() = v.getAnAccess() ) or - DataFlow::localFlow(pred, succ) + DataFlow::localFlowStep(pred, succ) }