Merge pull request #20761 from aschackmull/java/ssa-shared

Java: Replace SSA wrapper classes with shared implementation.
This commit is contained in:
Anders Schack-Mulligen
2025-11-18 13:31:50 +01:00
committed by GitHub
53 changed files with 1008 additions and 840 deletions

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The SSA interface has been updated and all classes and several predicates have been renamed. See the qldoc for more specific migration information.

View File

@@ -1808,6 +1808,52 @@ class VariableAssign extends VariableUpdate {
} }
} }
private newtype TVariableWrite =
TParamInit(Parameter p) or
TVarWriteExpr(VariableUpdate u)
/**
* A write to a variable. This is either a local variable declaration,
* including parameter declarations, or an update to a variable.
*/
class VariableWrite extends TVariableWrite {
/** Gets the expression representing this write, if any. */
Expr asExpr() { this = TVarWriteExpr(result) }
/**
* Gets the expression with the value being written, if any.
*
* This can be the same expression as returned by `asExpr()`, which is the
* case for, for example, `++x` and `x += e`. For simple assignments like
* `x = e`, `asExpr()` gets the whole assignment expression while
* `getValue()` gets the right-hand side `e`. Post-crement operations like
* `x++` do not have an expression with the value being written.
*/
Expr getValue() {
this.asExpr().(VariableAssign).getSource() = result or
this.asExpr().(AssignOp) = result or
this.asExpr().(PreIncExpr) = result or
this.asExpr().(PreDecExpr) = result
}
/** Holds if this write is an initialization of parameter `p`. */
predicate isParameterInit(Parameter p) { this = TParamInit(p) }
/** Gets a textual representation of this write. */
string toString() {
exists(Parameter p | this = TParamInit(p) and result = p.toString())
or
result = this.asExpr().toString()
}
/** Gets the location of this write. */
Location getLocation() {
exists(Parameter p | this = TParamInit(p) and result = p.getLocation())
or
result = this.asExpr().getLocation()
}
}
/** A type literal. For example, `String.class`. */ /** A type literal. For example, `String.class`. */
class TypeLiteral extends Expr, @typeliteral { class TypeLiteral extends Expr, @typeliteral {
/** Gets the access to the type whose class is accessed. */ /** Gets the access to the type whose class is accessed. */

View File

@@ -6,11 +6,12 @@ module;
import java import java
private import codeql.controlflow.ControlFlowReachability private import codeql.controlflow.ControlFlowReachability
private import semmle.code.java.dataflow.SSA as SSA private import semmle.code.java.dataflow.SSA
private import semmle.code.java.controlflow.Guards as Guards private import semmle.code.java.controlflow.Guards as Guards
private module ControlFlowInput implements InputSig<Location, ControlFlowNode, BasicBlock> { private module ControlFlowInput implements InputSig<Location, ControlFlowNode, BasicBlock> {
private import java as J private import java as J
import Ssa
AstNode getEnclosingAstNode(ControlFlowNode node) { node.getAstNode() = result } AstNode getEnclosingAstNode(ControlFlowNode node) { node.getAstNode() = result }
@@ -27,23 +28,6 @@ private module ControlFlowInput implements InputSig<Location, ControlFlowNode, B
class Expr = J::Expr; class Expr = J::Expr;
class SourceVariable = SSA::SsaSourceVariable;
class SsaDefinition = SSA::SsaVariable;
class SsaExplicitWrite extends SsaDefinition instanceof SSA::SsaExplicitUpdate {
Expr getValue() {
super.getDefiningExpr().(VariableAssign).getSource() = result or
super.getDefiningExpr().(AssignOp) = result
}
}
class SsaPhiDefinition = SSA::SsaPhiNode;
class SsaUncertainWrite extends SsaDefinition instanceof SSA::SsaUncertainImplicitUpdate {
SsaDefinition getPriorDefinition() { result = super.getPriorDef() }
}
class GuardValue = Guards::GuardValue; class GuardValue = Guards::GuardValue;
predicate ssaControlsBranchEdge(SsaDefinition def, BasicBlock bb1, BasicBlock bb2, GuardValue v) { predicate ssaControlsBranchEdge(SsaDefinition def, BasicBlock bb1, BasicBlock bb2, GuardValue v) {

View File

@@ -141,7 +141,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
private module GuardsInput implements SharedGuards::InputSig<Location, ControlFlowNode, BasicBlock> { private module GuardsInput implements SharedGuards::InputSig<Location, ControlFlowNode, BasicBlock> {
private import java as J private import java as J
private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.dataflow.internal.BaseSSA as Base
private import semmle.code.java.dataflow.NullGuards as NullGuards private import semmle.code.java.dataflow.NullGuards as NullGuards
class NormalExitNode = ControlFlow::NormalExitNode; class NormalExitNode = ControlFlow::NormalExitNode;
@@ -211,10 +211,10 @@ private module GuardsInput implements SharedGuards::InputSig<Location, ControlFl
f.getInitializer() = NullGuards::baseNotNullExpr() f.getInitializer() = NullGuards::baseNotNullExpr()
) )
or or
exists(CatchClause cc, LocalVariableDeclExpr decl, BaseSsaUpdate v | exists(CatchClause cc, LocalVariableDeclExpr decl, Base::SsaExplicitWrite v |
decl = cc.getVariable() and decl = cc.getVariable() and
decl = v.getDefiningExpr() and decl = v.getDefiningExpr() and
this = v.getAUse() this = v.getARead()
) )
} }
} }
@@ -407,30 +407,8 @@ private module LogicInputCommon {
} }
private module LogicInput_v1 implements GuardsImpl::LogicInputSig { private module LogicInput_v1 implements GuardsImpl::LogicInputSig {
private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.dataflow.internal.BaseSSA as Base
import Base::Ssa
final private class FinalBaseSsaVariable = BaseSsaVariable;
class SsaDefinition extends FinalBaseSsaVariable {
GuardsInput::Expr getARead() { result = this.getAUse() }
}
class SsaExplicitWrite extends SsaDefinition instanceof BaseSsaUpdate {
GuardsInput::Expr getValue() {
super.getDefiningExpr().(VariableAssign).getSource() = result or
super.getDefiningExpr().(AssignOp) = result
}
}
class SsaPhiDefinition extends SsaDefinition instanceof BaseSsaPhiNode {
predicate hasInputFromBlock(SsaDefinition inp, BasicBlock bb) {
super.hasInputFromBlock(inp, bb)
}
}
class SsaParameterInit extends SsaDefinition instanceof BaseSsaImplicitInit {
Parameter getParameter() { super.isParameterDefinition(result) }
}
predicate additionalNullCheck = LogicInputCommon::additionalNullCheck/4; predicate additionalNullCheck = LogicInputCommon::additionalNullCheck/4;
@@ -438,30 +416,8 @@ private module LogicInput_v1 implements GuardsImpl::LogicInputSig {
} }
private module LogicInput_v2 implements GuardsImpl::LogicInputSig { private module LogicInput_v2 implements GuardsImpl::LogicInputSig {
private import semmle.code.java.dataflow.SSA as SSA private import semmle.code.java.dataflow.SSA
import Ssa
final private class FinalSsaVariable = SSA::SsaVariable;
class SsaDefinition extends FinalSsaVariable {
GuardsInput::Expr getARead() { result = this.getAUse() }
}
class SsaExplicitWrite extends SsaDefinition instanceof SSA::SsaExplicitUpdate {
GuardsInput::Expr getValue() {
super.getDefiningExpr().(VariableAssign).getSource() = result or
super.getDefiningExpr().(AssignOp) = result
}
}
class SsaPhiDefinition extends SsaDefinition instanceof SSA::SsaPhiNode {
predicate hasInputFromBlock(SsaDefinition inp, BasicBlock bb) {
super.hasInputFromBlock(inp, bb)
}
}
class SsaParameterInit extends SsaDefinition instanceof SSA::SsaImplicitInit {
Parameter getParameter() { super.isParameterDefinition(result) }
}
predicate additionalNullCheck = LogicInputCommon::additionalNullCheck/4; predicate additionalNullCheck = LogicInputCommon::additionalNullCheck/4;

View File

@@ -34,8 +34,12 @@ predicate useUsePair(VarRead use1, VarRead use2) { adjacentUseUse+(use1, use2) }
* Other paths may also exist, so the SSA variables in `def` and `use` can be different. * Other paths may also exist, so the SSA variables in `def` and `use` can be different.
*/ */
predicate defUsePair(VariableUpdate def, VarRead use) { predicate defUsePair(VariableUpdate def, VarRead use) {
exists(SsaVariable v | exists(SsaDefinition v, SsaExplicitWrite write |
v.getAUse() = use and v.getAnUltimateDefinition().(SsaExplicitUpdate).getDefiningExpr() = def v.getARead() = use and write.getDefiningExpr() = def
|
v.getAnUltimateDefinition() = write
or
v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = write
) )
} }
@@ -46,7 +50,9 @@ predicate defUsePair(VariableUpdate def, VarRead use) {
* Other paths may also exist, so the SSA variables can be different. * Other paths may also exist, so the SSA variables can be different.
*/ */
predicate parameterDefUsePair(Parameter p, VarRead use) { predicate parameterDefUsePair(Parameter p, VarRead use) {
exists(SsaVariable v | exists(SsaDefinition v, SsaParameterInit init | v.getARead() = use and init.getParameter() = p |
v.getAUse() = use and v.getAnUltimateDefinition().(SsaImplicitInit).isParameterDefinition(p) v.getAnUltimateDefinition() = init
or
v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = init
) )
} }

View File

@@ -26,9 +26,9 @@ Expr enumConstEquality(Expr e, boolean polarity, EnumConstant c) {
} }
/** Gets an instanceof expression of `v` with type `type` */ /** Gets an instanceof expression of `v` with type `type` */
InstanceOfExpr instanceofExpr(SsaVariable v, RefType type) { InstanceOfExpr instanceofExpr(SsaDefinition v, RefType type) {
result.getCheckedType() = type and result.getCheckedType() = type and
result.getExpr() = v.getAUse() result.getExpr() = v.getARead()
} }
/** /**
@@ -37,8 +37,8 @@ InstanceOfExpr instanceofExpr(SsaVariable v, RefType type) {
* *
* Note this includes Kotlin's `==` and `!=` operators, which are value-equality tests. * Note this includes Kotlin's `==` and `!=` operators, which are value-equality tests.
*/ */
EqualityTest varEqualityTestExpr(SsaVariable v1, SsaVariable v2, boolean isEqualExpr) { EqualityTest varEqualityTestExpr(SsaDefinition v1, SsaDefinition v2, boolean isEqualExpr) {
result.hasOperands(v1.getAUse(), v2.getAUse()) and result.hasOperands(v1.getARead(), v2.getARead()) and
isEqualExpr = result.polarity() isEqualExpr = result.polarity()
} }
@@ -91,37 +91,44 @@ Expr clearlyNotNullExpr(Expr reason) {
(reason = r1 or reason = r2) (reason = r1 or reason = r2)
) )
or or
exists(SsaVariable v, boolean branch, VarRead rval, Guard guard | exists(SsaDefinition v, boolean branch, VarRead rval, Guard guard |
guard = directNullGuard(v, branch, false) and guard = directNullGuard(v, branch, false) and
guard.controls(rval.getBasicBlock(), branch) and guard.controls(rval.getBasicBlock(), branch) and
reason = guard and reason = guard and
rval = v.getAUse() and rval = v.getARead() and
result = rval and result = rval and
not result = baseNotNullExpr() not result = baseNotNullExpr()
) )
or or
exists(SsaVariable v | exists(SsaDefinition v |
clearlyNotNull(v, reason) and clearlyNotNull(v, reason) and
result = v.getAUse() and result = v.getARead() and
not result = baseNotNullExpr()
)
or
exists(Field f |
result = f.getAnAccess() and
f.isFinal() and
f.getInitializer() = clearlyNotNullExpr(reason) and
not result = baseNotNullExpr() not result = baseNotNullExpr()
) )
} }
/** Holds if `v` is an SSA variable that is provably not `null`. */ /** Holds if `v` is an SSA variable that is provably not `null`. */
predicate clearlyNotNull(SsaVariable v, Expr reason) { predicate clearlyNotNull(SsaDefinition v, Expr reason) {
exists(Expr src | exists(Expr src |
src = v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() and src = v.(SsaExplicitWrite).getValue() and
src = clearlyNotNullExpr(reason) src = clearlyNotNullExpr(reason)
) )
or or
exists(CatchClause cc, LocalVariableDeclExpr decl | exists(CatchClause cc, LocalVariableDeclExpr decl |
decl = cc.getVariable() and decl = cc.getVariable() and
decl = v.(SsaExplicitUpdate).getDefiningExpr() and decl = v.(SsaExplicitWrite).getDefiningExpr() and
reason = decl reason = decl
) )
or or
exists(SsaVariable captured | exists(SsaDefinition captured |
v.(SsaImplicitInit).captures(captured) and v.(SsaCapturedDefinition).captures(captured) and
clearlyNotNull(captured, reason) clearlyNotNull(captured, reason)
) )
or or
@@ -136,7 +143,7 @@ predicate clearlyNotNull(SsaVariable v, Expr reason) {
Expr clearlyNotNullExpr() { result = clearlyNotNullExpr(_) } Expr clearlyNotNullExpr() { result = clearlyNotNullExpr(_) }
/** Holds if `v` is an SSA variable that is provably not `null`. */ /** Holds if `v` is an SSA variable that is provably not `null`. */
predicate clearlyNotNull(SsaVariable v) { clearlyNotNull(v, _) } predicate clearlyNotNull(SsaDefinition v) { clearlyNotNull(v, _) }
/** /**
* Holds if the evaluation of a call to `m` resulting in the value `branch` * Holds if the evaluation of a call to `m` resulting in the value `branch`
@@ -207,7 +214,7 @@ deprecated Expr basicOrCustomNullGuard(Expr e, boolean branch, boolean isnull) {
* If `result` evaluates to `branch`, then `v` is guaranteed to be null if `isnull` * If `result` evaluates to `branch`, then `v` is guaranteed to be null if `isnull`
* is true, and non-null if `isnull` is false. * is true, and non-null if `isnull` is false.
*/ */
Expr directNullGuard(SsaVariable v, boolean branch, boolean isnull) { Expr directNullGuard(SsaDefinition v, boolean branch, boolean isnull) {
result = basicNullGuard(sameValue(v, _), branch, isnull) result = basicNullGuard(sameValue(v, _), branch, isnull)
} }
@@ -219,7 +226,7 @@ Expr directNullGuard(SsaVariable v, boolean branch, boolean isnull) {
* If `result` evaluates to `branch`, then `v` is guaranteed to be null if `isnull` * If `result` evaluates to `branch`, then `v` is guaranteed to be null if `isnull`
* is true, and non-null if `isnull` is false. * is true, and non-null if `isnull` is false.
*/ */
deprecated Guard nullGuard(SsaVariable v, boolean branch, boolean isnull) { deprecated Guard nullGuard(SsaDefinition v, boolean branch, boolean isnull) {
result = directNullGuard(v, branch, isnull) result = directNullGuard(v, branch, isnull)
} }
@@ -228,7 +235,9 @@ deprecated Guard nullGuard(SsaVariable v, boolean branch, boolean isnull) {
* from `bb1` to `bb2` implies that `v` is guaranteed to be null if `isnull` is * from `bb1` to `bb2` implies that `v` is guaranteed to be null if `isnull` is
* true, and non-null if `isnull` is false. * true, and non-null if `isnull` is false.
*/ */
predicate nullGuardControlsBranchEdge(SsaVariable v, boolean isnull, BasicBlock bb1, BasicBlock bb2) { predicate nullGuardControlsBranchEdge(
SsaDefinition v, boolean isnull, BasicBlock bb1, BasicBlock bb2
) {
exists(GuardValue gv | exists(GuardValue gv |
Guards_v3::ssaControlsBranchEdge(v, bb1, bb2, gv) and Guards_v3::ssaControlsBranchEdge(v, bb1, bb2, gv) and
gv.isNullness(isnull) gv.isNullness(isnull)
@@ -240,7 +249,7 @@ predicate nullGuardControlsBranchEdge(SsaVariable v, boolean isnull, BasicBlock
* `bb` `v` is guaranteed to be null if `isnull` is true, and non-null if * `bb` `v` is guaranteed to be null if `isnull` is true, and non-null if
* `isnull` is false. * `isnull` is false.
*/ */
predicate nullGuardControls(SsaVariable v, boolean isnull, BasicBlock bb) { predicate nullGuardControls(SsaDefinition v, boolean isnull, BasicBlock bb) {
exists(GuardValue gv | exists(GuardValue gv |
Guards_v3::ssaControls(v, bb, gv) and Guards_v3::ssaControls(v, bb, gv) and
gv.isNullness(isnull) gv.isNullness(isnull)
@@ -263,6 +272,6 @@ predicate guardSuggestsExprMaybeNull(Expr guard, Expr e) {
/** /**
* Holds if `guard` is a guard expression that suggests that `v` might be null. * Holds if `guard` is a guard expression that suggests that `v` might be null.
*/ */
predicate guardSuggestsVarMaybeNull(Expr guard, SsaVariable v) { predicate guardSuggestsVarMaybeNull(Expr guard, SsaDefinition v) {
guardSuggestsExprMaybeNull(guard, sameValue(v, _)) guardSuggestsExprMaybeNull(guard, sameValue(v, _))
} }

View File

@@ -113,7 +113,7 @@ predicate dereference(Expr e) {
* *
* The `VarAccess` is included for nicer error reporting. * The `VarAccess` is included for nicer error reporting.
*/ */
private ControlFlowNode varDereference(SsaVariable v, VarAccess va) { private ControlFlowNode varDereference(SsaDefinition v, VarAccess va) {
dereference(result.asExpr()) and dereference(result.asExpr()) and
result.asExpr() = sameValue(v, va) result.asExpr() = sameValue(v, va)
} }
@@ -121,7 +121,7 @@ private ControlFlowNode varDereference(SsaVariable v, VarAccess va) {
/** /**
* The first dereference of a variable in a given `BasicBlock`. * The first dereference of a variable in a given `BasicBlock`.
*/ */
private predicate firstVarDereferenceInBlock(BasicBlock bb, SsaVariable v, VarAccess va) { private predicate firstVarDereferenceInBlock(BasicBlock bb, SsaDefinition v, VarAccess va) {
exists(ControlFlowNode n | exists(ControlFlowNode n |
varDereference(v, va) = n and varDereference(v, va) = n and
n.getBasicBlock() = bb and n.getBasicBlock() = bb and
@@ -135,14 +135,14 @@ private predicate firstVarDereferenceInBlock(BasicBlock bb, SsaVariable v, VarAc
} }
/** A variable suspected of being `null`. */ /** A variable suspected of being `null`. */
private predicate varMaybeNull(SsaVariable v, ControlFlowNode node, string msg, Expr reason) { private predicate varMaybeNull(SsaDefinition v, ControlFlowNode node, string msg, Expr reason) {
// A variable compared to null might be null. // A variable compared to null might be null.
exists(Expr e | exists(Expr e |
reason = e and reason = e and
msg = "as suggested by $@ null guard" and msg = "as suggested by $@ null guard" and
guardSuggestsVarMaybeNull(e, v) and guardSuggestsVarMaybeNull(e, v) and
node = v.getCfgNode() and node = v.getControlFlowNode() and
not v instanceof SsaPhiNode and not v instanceof SsaPhiDefinition and
not clearlyNotNull(v) and not clearlyNotNull(v) and
// Comparisons in finally blocks are excluded since missing exception edges in the CFG could otherwise yield FPs. // Comparisons in finally blocks are excluded since missing exception edges in the CFG could otherwise yield FPs.
not exists(TryStmt try | try.getFinally() = e.getEnclosingStmt().getEnclosingStmt*()) and not exists(TryStmt try | try.getFinally() = e.getEnclosingStmt().getEnclosingStmt*()) and
@@ -151,13 +151,13 @@ private predicate varMaybeNull(SsaVariable v, ControlFlowNode node, string msg,
not exists(MethodCall ma | ma.getAnArgument().getAChildExpr*() = e) not exists(MethodCall ma | ma.getAnArgument().getAChildExpr*() = e)
) and ) and
// Don't use a guard as reason if there is a null assignment. // Don't use a guard as reason if there is a null assignment.
not v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = nullExpr() not v.(SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = nullExpr()
) )
or or
// A parameter might be null if there is a null argument somewhere. // A parameter might be null if there is a null argument somewhere.
exists(Parameter p, Expr arg | exists(Parameter p, Expr arg |
v.(SsaImplicitInit).isParameterDefinition(p) and v.(SsaParameterInit).getParameter() = p and
node = v.getCfgNode() and node = v.getControlFlowNode() and
p.getAnArgument() = arg and p.getAnArgument() = arg and
reason = arg and reason = arg and
msg = "because of $@ null argument" and msg = "because of $@ null argument" and
@@ -167,7 +167,7 @@ private predicate varMaybeNull(SsaVariable v, ControlFlowNode node, string msg,
or or
// If the source of a variable is null then the variable may be null. // If the source of a variable is null then the variable may be null.
exists(VariableAssign def | exists(VariableAssign def |
v.(SsaExplicitUpdate).getDefiningExpr() = def and v.(SsaExplicitWrite).getDefiningExpr() = def and
def.getSource() = nullExpr(node.asExpr()) and def.getSource() = nullExpr(node.asExpr()) and
reason = def and reason = def and
msg = "because of $@ assignment" msg = "because of $@ assignment"
@@ -179,26 +179,26 @@ private Expr nonEmptyExpr() {
// An array creation with a known positive size is trivially non-empty. // An array creation with a known positive size is trivially non-empty.
result.(ArrayCreationExpr).getFirstDimensionSize() > 0 result.(ArrayCreationExpr).getFirstDimensionSize() > 0
or or
exists(SsaVariable v | exists(SsaDefinition v |
// A use of an array variable is non-empty if... // A use of an array variable is non-empty if...
result = v.getAUse() and result = v.getARead() and
v.getSourceVariable().getType() instanceof Array v.getSourceVariable().getType() instanceof Array
| |
// ...its definition is non-empty... // ...its definition is non-empty...
v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = nonEmptyExpr() v.(SsaExplicitWrite).getValue() = nonEmptyExpr()
or or
// ...or it is guarded by a condition proving its length to be non-zero. // ...or it is guarded by a condition proving its length to be non-zero.
exists(ConditionBlock cond, boolean branch, FieldAccess length | exists(ConditionBlock cond, boolean branch, FieldAccess length |
cond.controls(result.getBasicBlock(), branch) and cond.controls(result.getBasicBlock(), branch) and
cond.getCondition() = nonZeroGuard(length, branch) and cond.getCondition() = nonZeroGuard(length, branch) and
length.getField().hasName("length") and length.getField().hasName("length") and
length.getQualifier() = v.getAUse() length.getQualifier() = v.getARead()
) )
) )
or or
exists(SsaVariable v | exists(SsaDefinition v |
// A use of a Collection variable is non-empty if... // A use of a Collection variable is non-empty if...
result = v.getAUse() and result = v.getARead() and
v.getSourceVariable().getType() instanceof CollectionType and v.getSourceVariable().getType() instanceof CollectionType and
exists(ConditionBlock cond, boolean branch, Expr c | exists(ConditionBlock cond, boolean branch, Expr c |
// ...it is guarded by a condition... // ...it is guarded by a condition...
@@ -216,13 +216,13 @@ private Expr nonEmptyExpr() {
// ...and the condition proves that it is non-empty, either by using the `isEmpty` method... // ...and the condition proves that it is non-empty, either by using the `isEmpty` method...
c.(MethodCall).getMethod().hasName("isEmpty") and c.(MethodCall).getMethod().hasName("isEmpty") and
branch = false and branch = false and
c.(MethodCall).getQualifier() = v.getAUse() c.(MethodCall).getQualifier() = v.getARead()
or or
// ...or a check on its `size`. // ...or a check on its `size`.
exists(MethodCall size | exists(MethodCall size |
c = nonZeroGuard(size, branch) and c = nonZeroGuard(size, branch) and
size.getMethod().hasName("size") and size.getMethod().hasName("size") and
size.getQualifier() = v.getAUse() size.getQualifier() = v.getARead()
) )
) )
) )
@@ -249,9 +249,9 @@ private predicate impossibleEdge(BasicBlock bb1, BasicBlock bb2) {
} }
private module NullnessConfig implements ControlFlowReachability::ConfigSig { private module NullnessConfig implements ControlFlowReachability::ConfigSig {
predicate source(ControlFlowNode node, SsaVariable def) { varMaybeNull(def, node, _, _) } predicate source(ControlFlowNode node, SsaDefinition def) { varMaybeNull(def, node, _, _) }
predicate sink(ControlFlowNode node, SsaVariable def) { varDereference(def, _) = node } predicate sink(ControlFlowNode node, SsaDefinition def) { varDereference(def, _) = node }
predicate barrierValue(GuardValue gv) { gv.isNullness(false) } predicate barrierValue(GuardValue gv) { gv.isNullness(false) }
@@ -266,7 +266,7 @@ private module NullnessFlow = ControlFlowReachability::Flow<NullnessConfig>;
* Holds if the dereference of `v` at `va` might be `null`. * Holds if the dereference of `v` at `va` might be `null`.
*/ */
predicate nullDeref(SsaSourceVariable v, VarAccess va, string msg, Expr reason) { predicate nullDeref(SsaSourceVariable v, VarAccess va, string msg, Expr reason) {
exists(SsaVariable origin, SsaVariable ssa, ControlFlowNode src, ControlFlowNode sink | exists(SsaDefinition origin, SsaDefinition ssa, ControlFlowNode src, ControlFlowNode sink |
varMaybeNull(origin, src, msg, reason) and varMaybeNull(origin, src, msg, reason) and
NullnessFlow::flow(src, origin, sink, ssa) and NullnessFlow::flow(src, origin, sink, ssa) and
ssa.getSourceVariable() = v and ssa.getSourceVariable() = v and
@@ -278,9 +278,9 @@ predicate nullDeref(SsaSourceVariable v, VarAccess va, string msg, Expr reason)
* A dereference of a variable that is always `null`. * A dereference of a variable that is always `null`.
*/ */
predicate alwaysNullDeref(SsaSourceVariable v, VarAccess va) { predicate alwaysNullDeref(SsaSourceVariable v, VarAccess va) {
exists(BasicBlock bb, SsaVariable ssa | exists(BasicBlock bb, SsaDefinition ssa |
forall(SsaVariable def | def = ssa.getAnUltimateDefinition() | forall(SsaDefinition def | def = ssa.getAnUltimateDefinition() |
def.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = alwaysNullExpr() def.(SsaExplicitWrite).getValue() = alwaysNullExpr()
) )
or or
nullGuardControls(ssa, true, bb) and nullGuardControls(ssa, true, bb) and

View File

@@ -242,17 +242,17 @@ module Sem implements Semantic<Location> {
Type getSsaType(SsaVariable var) { result = var.getSourceVariable().getType() } Type getSsaType(SsaVariable var) { result = var.getSourceVariable().getType() }
final private class FinalSsaVariable = SSA::SsaVariable; final private class FinalSsaVariable = SSA::SsaDefinition;
class SsaVariable extends FinalSsaVariable { class SsaVariable extends FinalSsaVariable {
Expr getAUse() { result = super.getAUse() } Expr getAUse() { result = super.getARead() }
} }
class SsaPhiNode extends SsaVariable instanceof SSA::SsaPhiNode { class SsaPhiNode extends SsaVariable instanceof SSA::SsaPhiDefinition {
predicate hasInputFromBlock(SsaVariable inp, BasicBlock bb) { super.hasInputFromBlock(inp, bb) } predicate hasInputFromBlock(SsaVariable inp, BasicBlock bb) { super.hasInputFromBlock(inp, bb) }
} }
class SsaExplicitUpdate extends SsaVariable instanceof SSA::SsaExplicitUpdate { class SsaExplicitUpdate extends SsaVariable instanceof SSA::SsaExplicitWrite {
Expr getDefiningExpr() { result = super.getDefiningExpr() } Expr getDefiningExpr() { result = super.getDefiningExpr() }
} }

View File

@@ -30,17 +30,17 @@ predicate eqFlowCond = U::eqFlowCond/5;
* only other input to `phi` is a `null` value. * only other input to `phi` is a `null` value.
* *
* Note that the declared type of `phi` is `SsaVariable` instead of * Note that the declared type of `phi` is `SsaVariable` instead of
* `SsaPhiNode` in order for the reflexive case of `nonNullSsaFwdStep*(..)` to * `SsaPhiDefinition` in order for the reflexive case of `nonNullSsaFwdStep*(..)` to
* have non-`SsaPhiNode` results. * have non-`SsaPhiDefinition` results.
*/ */
private predicate nonNullSsaFwdStep(SsaVariable v, SsaVariable phi) { private predicate nonNullSsaFwdStep(SsaDefinition v, SsaDefinition phi) {
exists(SsaExplicitUpdate vnull, SsaPhiNode phi0 | phi0 = phi | exists(SsaExplicitWrite vnull, SsaPhiDefinition phi0 | phi0 = phi |
2 = strictcount(phi0.getAPhiInput()) and 2 = strictcount(phi0.getAnInput()) and
vnull = phi0.getAPhiInput() and vnull = phi0.getAnInput() and
v = phi0.getAPhiInput() and v = phi0.getAnInput() and
not backEdge(phi0, v, _) and not backEdge(phi0, v, _) and
vnull != v and vnull != v and
vnull.getDefiningExpr().(VariableAssign).getSource() instanceof NullLiteral vnull.getValue() instanceof NullLiteral
) )
} }
@@ -56,13 +56,13 @@ private predicate nonNullDefStep(Expr e1, Expr e2) {
* explicit `ArrayCreationExpr` definition and that the definition does not go * explicit `ArrayCreationExpr` definition and that the definition does not go
* through a back edge. * through a back edge.
*/ */
ArrayCreationExpr getArrayDef(SsaVariable v) { ArrayCreationExpr getArrayDef(SsaDefinition v) {
exists(Expr src | exists(Expr src |
v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = src and v.(SsaExplicitWrite).getValue() = src and
nonNullDefStep*(result, src) nonNullDefStep*(result, src)
) )
or or
exists(SsaVariable mid | exists(SsaDefinition mid |
result = getArrayDef(mid) and result = getArrayDef(mid) and
nonNullSsaFwdStep(mid, v) nonNullSsaFwdStep(mid, v)
) )
@@ -74,9 +74,9 @@ ArrayCreationExpr getArrayDef(SsaVariable v) {
* `arrlen` without going through a back edge. * `arrlen` without going through a back edge.
*/ */
private predicate arrayLengthDef(FieldRead arrlen, ArrayCreationExpr def) { private predicate arrayLengthDef(FieldRead arrlen, ArrayCreationExpr def) {
exists(SsaVariable arr | exists(SsaDefinition arr |
arrlen.getField() instanceof ArrayLengthField and arrlen.getField() instanceof ArrayLengthField and
arrlen.getQualifier() = arr.getAUse() and arrlen.getQualifier() = arr.getARead() and
def = getArrayDef(arr) def = getArrayDef(arr)
) )
} }
@@ -86,9 +86,9 @@ pragma[nomagic]
private predicate constantIntegerExpr(Expr e, int val) { private predicate constantIntegerExpr(Expr e, int val) {
e.(CompileTimeConstantExpr).getIntValue() = val e.(CompileTimeConstantExpr).getIntValue() = val
or or
exists(SsaExplicitUpdate v, Expr src | exists(SsaExplicitWrite v, Expr src |
e = v.getAUse() and e = v.getARead() and
src = v.getDefiningExpr().(VariableAssign).getSource() and src = v.getValue() and
constantIntegerExpr(src, val) constantIntegerExpr(src, val)
) )
or or
@@ -112,9 +112,9 @@ pragma[nomagic]
private predicate constantBooleanExpr(Expr e, boolean val) { private predicate constantBooleanExpr(Expr e, boolean val) {
e.(CompileTimeConstantExpr).getBooleanValue() = val e.(CompileTimeConstantExpr).getBooleanValue() = val
or or
exists(SsaExplicitUpdate v, Expr src | exists(SsaExplicitWrite v, Expr src |
e = v.getAUse() and e = v.getARead() and
src = v.getDefiningExpr().(VariableAssign).getSource() and src = v.getValue() and
constantBooleanExpr(src, val) constantBooleanExpr(src, val)
) )
or or
@@ -125,9 +125,9 @@ pragma[nomagic]
private predicate constantStringExpr(Expr e, string val) { private predicate constantStringExpr(Expr e, string val) {
e.(CompileTimeConstantExpr).getStringValue() = val e.(CompileTimeConstantExpr).getStringValue() = val
or or
exists(SsaExplicitUpdate v, Expr src | exists(SsaExplicitWrite v, Expr src |
e = v.getAUse() and e = v.getARead() and
src = v.getDefiningExpr().(VariableAssign).getSource() and src = v.getValue() and
constantStringExpr(src, val) constantStringExpr(src, val)
) )
} }

View File

@@ -5,16 +5,16 @@
* `ControlFlowNode` at which it is defined. Each SSA variable is defined * `ControlFlowNode` at which it is defined. Each SSA variable is defined
* either by a phi node, an implicit initial value (for parameters and fields), * either by a phi node, an implicit initial value (for parameters and fields),
* an explicit update, or an implicit update (for fields). * an explicit update, or an implicit update (for fields).
* An implicit update occurs either at a `Call` that might modify a field, at * An implicit update occurs either at a `Call` that might modify a field, or
* another update that can update the qualifier of a field, or at a `FieldRead` * at another update that can update the qualifier of a field.
* of the field in case the field is not amenable to a non-trivial SSA
* representation.
*/ */
overlay[local?] overlay[local?]
module; module;
import java import java
private import internal.SsaImpl private import internal.SsaImpl
import internal.SsaImpl::Ssa as Ssa
import Ssa
/** /**
* A fully qualified variable in the context of a `Callable` in which it is * A fully qualified variable in the context of a `Callable` in which it is
@@ -105,7 +105,7 @@ class SsaSourceVariable extends TSsaSourceVariable {
SsaSourceVariable getQualifier() { this = TQualifiedField(_, result, _) } SsaSourceVariable getQualifier() { this = TQualifiedField(_, result, _) }
/** Gets an SSA variable that has this variable as its underlying source variable. */ /** Gets an SSA variable that has this variable as its underlying source variable. */
SsaVariable getAnSsaVariable() { result.getSourceVariable() = this } SsaDefinition getAnSsaVariable() { result.getSourceVariable() = this }
} }
/** /**
@@ -138,22 +138,76 @@ class SsaSourceField extends SsaSourceVariable {
} }
} }
/** An SSA definition in a closure that captures a variable. */
class SsaCapturedDefinition extends SsaImplicitEntryDefinition {
SsaCapturedDefinition() { captures(this, _) }
override string toString() { result = "SSA capture def(" + this.getSourceVariable() + ")" }
/** Holds if this definition captures the value of `capturedvar`. */
predicate captures(SsaDefinition capturedvar) { captures(this, capturedvar) }
/**
* Gets a definition that ultimately defines the captured variable and is not itself a phi node.
*/
SsaDefinition getAnUltimateCapturedDefinition() {
exists(SsaDefinition capturedvar |
captures(this, capturedvar) and result = capturedvar.getAnUltimateDefinition()
)
}
}
/** /**
* An SSA definition representing the potential definition of a variable
* via a call.
*/
class SsaImplicitCallDefinition extends SsaImplicitWrite {
SsaImplicitCallDefinition() { isNonLocal(this) and not hasQualifierUpdate(this) }
override string toString() { result = "SSA call def(" + this.getSourceVariable() + ")" }
/**
* Gets a reachable `FieldWrite` that might represent this ssa update, if any.
*/
overlay[global]
FieldWrite getANonLocalUpdate() { result = getANonLocalUpdate(this) }
}
/** An SSA definition due to an update of the qualifier. */
class SsaImplicitQualifierDefinition extends SsaImplicitWrite {
SsaImplicitQualifierDefinition() { hasQualifierUpdate(this) }
override string toString() { result = "SSA qualifier def(" + this.getSourceVariable() + ")" }
}
/**
* Gets an access of the SSA source variable underlying this SSA variable
* that can be reached from this SSA variable without passing through any
* other uses, but potentially through phi nodes and uncertain implicit
* updates.
*/
VarRead ssaGetAFirstUse(SsaDefinition def) { firstUse(def, result) }
/**
* DEPRECATED: use `SsaDefinition` instead.
*
* An SSA variable. * An SSA variable.
*/ */
class SsaVariable extends Definition { class SsaVariable extends Definition {
/** Gets the SSA source variable underlying this SSA variable. */ /** Gets the SSA source variable underlying this SSA variable. */
SsaSourceVariable getSourceVariable() { result = super.getSourceVariable() } SsaSourceVariable getSourceVariable() { result = super.getSourceVariable() }
/** Gets the `ControlFlowNode` at which this SSA variable is defined. */ /**
* DEPRECATED: Use `getControlFlowNode()` instead.
*
* Gets the `ControlFlowNode` at which this SSA variable is defined.
*/
pragma[nomagic] pragma[nomagic]
ControlFlowNode getCfgNode() { ControlFlowNode getCfgNode() {
exists(BasicBlock bb, int i, int j | exists(BasicBlock bb, int i |
this.definesAt(_, bb, i) and this.definesAt(_, bb, i) and
// untracked definitions are inserted just before reads
(if this instanceof UntrackedDef then j = i + 1 else j = i) and
// phi nodes are inserted at position `-1` // phi nodes are inserted at position `-1`
result = bb.getNode(0.maximum(j)) result = bb.getNode(0.maximum(i))
) )
} }
@@ -166,10 +220,16 @@ class SsaVariable extends Definition {
/** Gets the `BasicBlock` in which this SSA variable is defined. */ /** Gets the `BasicBlock` in which this SSA variable is defined. */
BasicBlock getBasicBlock() { result = super.getBasicBlock() } BasicBlock getBasicBlock() { result = super.getBasicBlock() }
/** Gets an access of this SSA variable. */ /**
* DEPRECATED: Use `getARead()` instead.
*
* Gets an access of this SSA variable.
*/
VarRead getAUse() { result = getAUse(this) } VarRead getAUse() { result = getAUse(this) }
/** /**
* DEPRECATED: Use `ssaGetAFirstUse(SsaDefinition)` instead.
*
* Gets an access of the SSA source variable underlying this SSA variable * Gets an access of the SSA source variable underlying this SSA variable
* that can be reached from this SSA variable without passing through any * that can be reached from this SSA variable without passing through any
* other uses, but potentially through phi nodes and uncertain implicit * other uses, but potentially through phi nodes and uncertain implicit
@@ -178,34 +238,49 @@ class SsaVariable extends Definition {
* Subsequent uses can be found by following the steps defined by * Subsequent uses can be found by following the steps defined by
* `adjacentUseUse`. * `adjacentUseUse`.
*/ */
VarRead getAFirstUse() { firstUse(this, result) } deprecated VarRead getAFirstUse() { firstUse(this, result) }
/** Holds if this SSA variable is live at the end of `b`. */ /** Holds if this SSA variable is live at the end of `b`. */
predicate isLiveAtEndOfBlock(BasicBlock b) { ssaDefReachesEndOfBlock(b, this) } predicate isLiveAtEndOfBlock(BasicBlock b) { ssaDefReachesEndOfBlock(b, this) }
/** /**
* DEPRECATED.
*
* Gets an SSA variable whose value can flow to this one in one step. This * Gets an SSA variable whose value can flow to this one in one step. This
* includes inputs to phi nodes, the prior definition of uncertain updates, * includes inputs to phi nodes, the prior definition of uncertain updates,
* and the captured ssa variable for a closure variable. * and the captured ssa variable for a closure variable.
*/ */
SsaVariable getAPhiInputOrPriorDef() { deprecated SsaVariable getAPhiInputOrPriorDef() {
result = this.(SsaPhiNode).getAPhiInput() or result = this.(SsaPhiNode).getAPhiInput() or
result = this.(SsaUncertainImplicitUpdate).getPriorDef() or result = this.(SsaUncertainImplicitUpdate).getPriorDef() or
this.(SsaImplicitInit).captures(result) this.(SsaImplicitInit).captures(result)
} }
/** Gets a definition that ultimately defines this variable and is not itself a phi node. */ /**
SsaVariable getAnUltimateDefinition() { * DEPRECATED: Use `SsaCapturedDefinition::getAnUltimateCapturedDefinition()`
* and/or `SsaDefinition::getAnUltimateDefinition()` instead.
*
* Gets a definition that ultimately defines this variable and is not itself a phi node.
*/
deprecated SsaVariable getAnUltimateDefinition() {
result = this.getAPhiInputOrPriorDef*() and not result instanceof SsaPhiNode result = this.getAPhiInputOrPriorDef*() and not result instanceof SsaPhiNode
} }
} }
/** An SSA variable that either explicitly or implicitly updates the variable. */ /**
* DEPRECATED: use `SsaWriteDefinition` instead.
*
* An SSA variable that either explicitly or implicitly updates the variable.
*/
class SsaUpdate extends SsaVariable instanceof WriteDefinition { class SsaUpdate extends SsaVariable instanceof WriteDefinition {
SsaUpdate() { not this instanceof SsaImplicitInit } SsaUpdate() { not this instanceof SsaImplicitInit }
} }
/** An SSA variable that is defined by a `VariableUpdate`. */ /**
* DEPRECATED: Use `SsaExplicitWrite` instead.
*
* An SSA variable that is defined by a `VariableUpdate`.
*/
class SsaExplicitUpdate extends SsaUpdate { class SsaExplicitUpdate extends SsaUpdate {
private VariableUpdate upd; private VariableUpdate upd;
@@ -218,12 +293,14 @@ class SsaExplicitUpdate extends SsaUpdate {
} }
/** /**
* DEPRECATED: Use `SsaImplicitWrite` instead.
*
* An SSA variable that represents any sort of implicit update. This can be a * An SSA variable that represents any sort of implicit update. This can be a
* `Call` that might reach a non-local update of the field, an explicit or * `Call` that might reach a non-local update of the field, an explicit or
* implicit update of the qualifier of the field, or the implicit update that * implicit update of the qualifier of the field, or the implicit update that
* occurs just prior to a `FieldRead` of an untracked field. * occurs just prior to a `FieldRead` of an untracked field.
*/ */
class SsaImplicitUpdate extends SsaUpdate { deprecated class SsaImplicitUpdate extends SsaUpdate {
SsaImplicitUpdate() { not this instanceof SsaExplicitUpdate } SsaImplicitUpdate() { not this instanceof SsaExplicitUpdate }
override string toString() { override string toString() {
@@ -246,69 +323,89 @@ class SsaImplicitUpdate extends SsaUpdate {
} }
private string getKind() { private string getKind() {
this instanceof UntrackedDef and result = "untracked"
or
this.hasExplicitQualifierUpdate() and this.hasExplicitQualifierUpdate() and
result = "explicit qualifier" result = "explicit qualifier" // -> SSA qualifier def
or or
if this.hasImplicitQualifierUpdate() if this.hasImplicitQualifierUpdate()
then then
if isNonLocal(this) if isNonLocal(this)
then result = "nonlocal + nonlocal qualifier" then result = "nonlocal + nonlocal qualifier" // -> SSA qualifier def
else result = "nonlocal qualifier" else result = "nonlocal qualifier" // -> SSA qualifier def
else ( else (
isNonLocal(this) and result = "nonlocal" isNonLocal(this) and result = "nonlocal" // -> SSA call def
) )
} }
/** /**
* DEPRECATED: Use `SsaImplicitCallDefinition.getANonLocalUpdate()` instead.
*
* Gets a reachable `FieldWrite` that might represent this ssa update, if any. * Gets a reachable `FieldWrite` that might represent this ssa update, if any.
*/ */
overlay[global] overlay[global]
FieldWrite getANonLocalUpdate() { deprecated FieldWrite getANonLocalUpdate() { result = getANonLocalUpdate(this) }
exists(SsaSourceField f, Callable setter |
relevantFieldUpdate(setter, f.getField(), result) and
defUpdatesNamedField(this, f, setter)
)
}
/** /**
* DEPRECATED: Use `SsaImplicitQualifierDefinition` instead.
*
* Holds if this ssa variable might change the value to something unknown. * Holds if this ssa variable might change the value to something unknown.
* *
* Examples include updates that might change the value of the qualifier, or * Examples include updates that might change the value of the qualifier, or
* reads from untracked variables, for example those where the field or one * reads from untracked variables, for example those where the field or one
* of its qualifiers is volatile. * of its qualifiers is volatile.
*/ */
predicate assignsUnknownValue() { deprecated predicate assignsUnknownValue() {
this instanceof UntrackedDef
or
this.hasExplicitQualifierUpdate() this.hasExplicitQualifierUpdate()
or or
this.hasImplicitQualifierUpdate() this.hasImplicitQualifierUpdate()
} }
} }
overlay[global] private predicate hasQualifierUpdate(SsaImplicitWrite def) {
private predicate isNonLocalImpl(SsaImplicitUpdate su) { exists(su.getANonLocalUpdate()) } exists(SsaWriteDefinition qdef, BasicBlock bb, int i |
qdef.definesAt(def.getSourceVariable().getQualifier(), bb, i) and
private predicate isNonLocal(SsaImplicitUpdate su) = forceLocal(isNonLocalImpl/1)(su) def.definesAt(_, bb, i) and
not qdef instanceof SsaImplicitEntryDefinition
)
}
/** /**
* Gets a reachable `FieldWrite` that might represent this ssa update, if any.
*/
overlay[global]
private FieldWrite getANonLocalUpdate(SsaImplicitWrite calldef) {
exists(SsaSourceField f, Callable setter |
relevantFieldUpdate(setter, f.getField(), result) and
defUpdatesNamedField(calldef, f, setter)
)
}
overlay[global]
private predicate isNonLocalImpl(SsaImplicitWrite calldef) { exists(getANonLocalUpdate(calldef)) }
private predicate isNonLocal(SsaImplicitWrite calldef) = forceLocal(isNonLocalImpl/1)(calldef)
/**
* DEPRECATED: Use `SsaUncertainWrite` instead.
*
* An SSA variable that represents an uncertain implicit update of the value. * An SSA variable that represents an uncertain implicit update of the value.
* This is a `Call` that might reach a non-local update of the field or one of * This is a `Call` that might reach a non-local update of the field or one of
* its qualifiers. * its qualifiers.
*/ */
class SsaUncertainImplicitUpdate extends SsaImplicitUpdate { deprecated class SsaUncertainImplicitUpdate extends SsaImplicitUpdate {
SsaUncertainImplicitUpdate() { ssaUncertainImplicitUpdate(this) } SsaUncertainImplicitUpdate() { ssaUncertainImplicitUpdate(this) }
/** /**
* DEPRECATED: Use `getPriorDefinition()` instead.
*
* Gets the immediately preceding definition. Since this update is uncertain * Gets the immediately preceding definition. Since this update is uncertain
* the value from the preceding definition might still be valid. * the value from the preceding definition might still be valid.
*/ */
SsaVariable getPriorDef() { ssaDefReachesUncertainDef(result, this) } deprecated SsaVariable getPriorDef() { ssaDefReachesUncertainDef(result, this) }
} }
/** /**
* DEPRECATED: Use `SsaParameterInit`, `SsaImplicitEntryDefinition`, or `SsaCapturedDefinition` instead.
*
* An SSA variable that is defined by its initial value in the callable. This * An SSA variable that is defined by its initial value in the callable. This
* includes initial values of parameters, fields, and closure variables. * includes initial values of parameters, fields, and closure variables.
*/ */
@@ -321,6 +418,8 @@ class SsaImplicitInit extends SsaVariable instanceof WriteDefinition {
predicate captures(SsaVariable capturedvar) { captures(this, capturedvar) } predicate captures(SsaVariable capturedvar) { captures(this, capturedvar) }
/** /**
* DEPRECATED: Use `SsaParameterInit::getParameter()` instead.
*
* Holds if the SSA variable is a parameter defined by its initial value in the callable. * Holds if the SSA variable is a parameter defined by its initial value in the callable.
*/ */
predicate isParameterDefinition(Parameter p) { predicate isParameterDefinition(Parameter p) {
@@ -329,12 +428,20 @@ class SsaImplicitInit extends SsaVariable instanceof WriteDefinition {
} }
} }
/** An SSA phi node. */ /**
class SsaPhiNode extends SsaVariable instanceof PhiNode { * DEPRECATED: Use `SsaPhiDefinition` instead.
*
* An SSA phi node.
*/
deprecated class SsaPhiNode extends SsaVariable instanceof PhiNode {
override string toString() { result = "SSA phi(" + this.getSourceVariable() + ")" } override string toString() { result = "SSA phi(" + this.getSourceVariable() + ")" }
/** Gets an input to the phi node defining the SSA variable. */ /**
SsaVariable getAPhiInput() { this.hasInputFromBlock(result, _) } * DEPRECATED: Use `getAnInput()` instead.
*
* Gets an input to the phi node defining the SSA variable.
*/
deprecated SsaVariable getAPhiInput() { this.hasInputFromBlock(result, _) }
/** Gets an input to the phi node defining the SSA variable. */ /** Gets an input to the phi node defining the SSA variable. */
SsaVariable getAnInput() { this.hasInputFromBlock(result, _) } SsaVariable getAnInput() { this.hasInputFromBlock(result, _) }
@@ -357,10 +464,10 @@ private class RefTypeCastingExpr extends CastingExpr {
* *
* The `VarAccess` represents the access to `v` that `result` has the same value as. * The `VarAccess` represents the access to `v` that `result` has the same value as.
*/ */
Expr sameValue(SsaVariable v, VarAccess va) { Expr sameValue(SsaDefinition v, VarAccess va) {
result = v.getAUse() and result = va result = v.getARead() and result = va
or or
result.(AssignExpr).getDest() = va and result = v.(SsaExplicitUpdate).getDefiningExpr() result.(AssignExpr).getDest() = va and result = v.(SsaExplicitWrite).getDefiningExpr()
or or
result.(AssignExpr).getSource() = sameValue(v, va) result.(AssignExpr).getSource() = sameValue(v, va)
or or

View File

@@ -12,7 +12,7 @@ module;
import java as J import java as J
private import semmle.code.java.dispatch.VirtualDispatch private import semmle.code.java.dispatch.VirtualDispatch
private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.dataflow.internal.BaseSSA as Base
private import semmle.code.java.controlflow.Guards private import semmle.code.java.controlflow.Guards
private import codeql.typeflow.TypeFlow private import codeql.typeflow.TypeFlow
private import codeql.typeflow.UniversalFlow as UniversalFlow private import codeql.typeflow.UniversalFlow as UniversalFlow
@@ -27,7 +27,7 @@ private RefType boxIfNeeded(J::Type t) {
module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> { module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
private newtype TFlowNode = private newtype TFlowNode =
TField(Field f) { not f.getType() instanceof PrimitiveType } or TField(Field f) { not f.getType() instanceof PrimitiveType } or
TSsa(BaseSsaVariable ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or TSsa(Base::SsaDefinition ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or
TExpr(Expr e) or TExpr(Expr e) or
TMethod(Method m) { not m.getReturnType() instanceof PrimitiveType } TMethod(Method m) { not m.getReturnType() instanceof PrimitiveType }
@@ -55,7 +55,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
Field asField() { this = TField(result) } Field asField() { this = TField(result) }
/** Gets the SSA variable corresponding to this node, if any. */ /** Gets the SSA variable corresponding to this node, if any. */
BaseSsaVariable asSsa() { this = TSsa(result) } Base::SsaDefinition asSsa() { this = TSsa(result) }
/** Gets the expression corresponding to this node, if any. */ /** Gets the expression corresponding to this node, if any. */
Expr asExpr() { this = TExpr(result) } Expr asExpr() { this = TExpr(result) }
@@ -107,7 +107,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
not e.(FieldAccess).getField() = f not e.(FieldAccess).getField() = f
) )
or or
n2.asSsa().(BaseSsaPhiNode).getAnUltimateLocalDefinition() = n1.asSsa() n2.asSsa().(Base::SsaPhiDefinition).getAnUltimateDefinition() = n1.asSsa()
or or
exists(ReturnStmt ret | exists(ReturnStmt ret |
n2.asMethod() = ret.getEnclosingCallable() and ret.getResult() = n1.asExpr() n2.asMethod() = ret.getEnclosingCallable() and ret.getResult() = n1.asExpr()
@@ -118,14 +118,14 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
exists(Argument arg, Parameter p | exists(Argument arg, Parameter p |
privateParamArg(p, arg) and privateParamArg(p, arg) and
n1.asExpr() = arg and n1.asExpr() = arg and
n2.asSsa().(BaseSsaImplicitInit).isParameterDefinition(p) and n2.asSsa().(Base::SsaParameterInit).getParameter() = p and
// skip trivial recursion // skip trivial recursion
not arg = n2.asSsa().getAUse() not arg = n2.asSsa().getARead()
) )
or or
n2.asExpr() = n1.asField().getAnAccess() n2.asExpr() = n1.asField().getAnAccess()
or or
n2.asExpr() = n1.asSsa().getAUse() n2.asExpr() = n1.asSsa().getARead()
or or
n2.asExpr().(CastingExpr).getExpr() = n1.asExpr() and n2.asExpr().(CastingExpr).getExpr() = n1.asExpr() and
not n2.asExpr().getType() instanceof PrimitiveType not n2.asExpr().getType() instanceof PrimitiveType
@@ -133,9 +133,9 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
n2.asExpr().(AssignExpr).getSource() = n1.asExpr() and n2.asExpr().(AssignExpr).getSource() = n1.asExpr() and
not n2.asExpr().getType() instanceof PrimitiveType not n2.asExpr().getType() instanceof PrimitiveType
or or
n2.asSsa().(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr() n2.asSsa().(Base::SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
or or
n2.asSsa().(BaseSsaImplicitInit).captures(n1.asSsa()) n2.asSsa().(Base::SsaCapturedDefinition).captures(n1.asSsa())
or or
n2.asExpr().(NotNullExpr).getExpr() = n1.asExpr() n2.asExpr().(NotNullExpr).getExpr() = n1.asExpr()
} }
@@ -147,7 +147,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
n.asExpr() instanceof NullLiteral n.asExpr() instanceof NullLiteral
or or
exists(LocalVariableDeclExpr decl | exists(LocalVariableDeclExpr decl |
n.asSsa().(BaseSsaUpdate).getDefiningExpr() = decl and n.asSsa().(Base::SsaExplicitWrite).getDefiningExpr() = decl and
not decl.hasImplicitInit() and not decl.hasImplicitInit() and
not exists(decl.getInitOrPatternSource()) not exists(decl.getInitOrPatternSource())
) )
@@ -216,7 +216,9 @@ private module Input implements TypeFlowInput<Location> {
) )
} }
private predicate upcastEnhancedForStmtAux(BaseSsaUpdate v, RefType t, RefType t1, RefType t2) { private predicate upcastEnhancedForStmtAux(
Base::SsaExplicitWrite v, RefType t, RefType t1, RefType t2
) {
exists(EnhancedForStmt for | exists(EnhancedForStmt for |
for.getVariable() = v.getDefiningExpr() and for.getVariable() = v.getDefiningExpr() and
v.getSourceVariable().getType().getErasure() = t2 and v.getSourceVariable().getType().getErasure() = t2 and
@@ -230,7 +232,7 @@ private module Input implements TypeFlowInput<Location> {
* the type of the elements being iterated over, and this type is more precise * the type of the elements being iterated over, and this type is more precise
* than the type of `v`. * than the type of `v`.
*/ */
private predicate upcastEnhancedForStmt(BaseSsaUpdate v, RefType t) { private predicate upcastEnhancedForStmt(Base::SsaExplicitWrite v, RefType t) {
exists(RefType t1, RefType t2 | exists(RefType t1, RefType t2 |
upcastEnhancedForStmtAux(v, t, t1, t2) and upcastEnhancedForStmtAux(v, t, t1, t2) and
t1.getASourceSupertype+() = t2 t1.getASourceSupertype+() = t2
@@ -238,9 +240,9 @@ private module Input implements TypeFlowInput<Location> {
} }
private predicate downcastSuccessorAux( private predicate downcastSuccessorAux(
CastingExpr cast, BaseSsaVariable v, RefType t, RefType t1, RefType t2 CastingExpr cast, Base::SsaDefinition v, RefType t, RefType t1, RefType t2
) { ) {
cast.getExpr() = v.getAUse() and cast.getExpr() = v.getARead() and
t = cast.getType() and t = cast.getType() and
t1 = t.getErasure() and t1 = t.getErasure() and
t2 = v.getSourceVariable().getType().getErasure() t2 = v.getSourceVariable().getType().getErasure()
@@ -250,10 +252,10 @@ private module Input implements TypeFlowInput<Location> {
* Holds if `va` is an access to a value that has previously been downcast to `t`. * Holds if `va` is an access to a value that has previously been downcast to `t`.
*/ */
private predicate downcastSuccessor(VarAccess va, RefType t) { private predicate downcastSuccessor(VarAccess va, RefType t) {
exists(CastingExpr cast, BaseSsaVariable v, RefType t1, RefType t2 | exists(CastingExpr cast, Base::SsaDefinition v, RefType t1, RefType t2 |
downcastSuccessorAux(pragma[only_bind_into](cast), v, t, t1, t2) and downcastSuccessorAux(pragma[only_bind_into](cast), v, t, t1, t2) and
t1.getASourceSupertype+() = t2 and t1.getASourceSupertype+() = t2 and
va = v.getAUse() and va = v.getARead() and
dominates(cast.getControlFlowNode(), va.getControlFlowNode()) and dominates(cast.getControlFlowNode(), va.getControlFlowNode()) and
dominates(cast.getControlFlowNode().getANormalSuccessor(), va.getControlFlowNode()) dominates(cast.getControlFlowNode().getANormalSuccessor(), va.getControlFlowNode())
) )
@@ -263,9 +265,9 @@ private module Input implements TypeFlowInput<Location> {
* Holds if `va` is an access to a value that is guarded by `instanceof t` or `case e t`. * Holds if `va` is an access to a value that is guarded by `instanceof t` or `case e t`.
*/ */
private predicate typeTestGuarded(VarAccess va, RefType t) { private predicate typeTestGuarded(VarAccess va, RefType t) {
exists(Guard typeTest, BaseSsaVariable v | exists(Guard typeTest, Base::SsaDefinition v |
typeTest.appliesTypeTest(v.getAUse(), t, _) and typeTest.appliesTypeTest(v.getARead(), t, _) and
va = v.getAUse() and va = v.getARead() and
guardControls_v1(typeTest, va.getBasicBlock(), true) guardControls_v1(typeTest, va.getBasicBlock(), true)
) )
} }
@@ -274,12 +276,12 @@ private module Input implements TypeFlowInput<Location> {
* Holds if `aa` is an access to a value that is guarded by `instanceof t` or `case e t`. * Holds if `aa` is an access to a value that is guarded by `instanceof t` or `case e t`.
*/ */
private predicate arrayTypeTestGuarded(ArrayAccess aa, RefType t) { private predicate arrayTypeTestGuarded(ArrayAccess aa, RefType t) {
exists(Guard typeTest, BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1 | exists(Guard typeTest, Base::SsaDefinition v1, Base::SsaDefinition v2, ArrayAccess aa1 |
typeTest.appliesTypeTest(aa1, t, _) and typeTest.appliesTypeTest(aa1, t, _) and
aa1.getArray() = v1.getAUse() and aa1.getArray() = v1.getARead() and
aa1.getIndexExpr() = v2.getAUse() and aa1.getIndexExpr() = v2.getARead() and
aa.getArray() = v1.getAUse() and aa.getArray() = v1.getARead() and
aa.getIndexExpr() = v2.getAUse() and aa.getIndexExpr() = v2.getARead() and
guardControls_v1(typeTest, aa.getBasicBlock(), true) guardControls_v1(typeTest, aa.getBasicBlock(), true)
) )
} }
@@ -321,14 +323,14 @@ private module Input implements TypeFlowInput<Location> {
* Holds if `ioe` checks `v`, its true-successor is `bb`, and `bb` has multiple * Holds if `ioe` checks `v`, its true-successor is `bb`, and `bb` has multiple
* predecessors. * predecessors.
*/ */
private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, BaseSsaVariable v) { private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, Base::SsaDefinition v) {
ioe.getExpr() = v.getAUse() and ioe.getExpr() = v.getARead() and
strictcount(bb.getAPredecessor()) > 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, Base::SsaDefinition v) {
strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) = strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) =
strictcount(bb.getAPredecessor()) strictcount(bb.getAPredecessor())
} }
@@ -338,10 +340,10 @@ private module Input implements TypeFlowInput<Location> {
* `instanceof t_i` where `t` is one of those `t_i`. * `instanceof t_i` where `t` is one of those `t_i`.
*/ */
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, Base::SsaDefinition v, VarAccess va |
instanceofDisjunction(bb, v) and instanceofDisjunction(bb, v) and
bb.dominates(va.getBasicBlock()) and bb.dominates(va.getBasicBlock()) and
va = v.getAUse() and va = v.getARead() and
instanceofDisjunct(ioe, bb, v) and instanceofDisjunct(ioe, bb, v) and
t = ioe.getSyntacticCheckedType() and t = ioe.getSyntacticCheckedType() and
n.asExpr() = va n.asExpr() = va

View File

@@ -25,7 +25,8 @@ private module BaseSsaStage {
predicate backref() { predicate backref() {
(exists(TLocalVar(_, _)) implies any()) and (exists(TLocalVar(_, _)) implies any()) and
(exists(any(BaseSsaSourceVariable v).getAnAccess()) implies any()) and (exists(any(BaseSsaSourceVariable v).getAnAccess()) implies any()) and
(exists(getAUse(_)) implies any()) (exists(any(SsaDefinition def).getARead()) implies any()) and
(captures(_, _) implies any())
} }
} }
@@ -157,7 +158,7 @@ private module BaseSsaImpl {
private import BaseSsaImpl private import BaseSsaImpl
private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> { private module SsaImplInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
class SourceVariable = BaseSsaSourceVariable; class SourceVariable = BaseSsaSourceVariable;
/** /**
@@ -169,7 +170,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock>
certain = true certain = true
or or
hasEntryDef(v, bb) and hasEntryDef(v, bb) and
i = 0 and i = -1 and
certain = true certain = true
} }
@@ -189,67 +190,46 @@ private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock>
} }
} }
private module Impl = SsaImplCommon::Make<Location, Cfg, SsaInput>; private module Impl = SsaImplCommon::Make<Location, Cfg, SsaImplInput>;
private module SsaInput implements Impl::SsaInputSig {
private import java as J
class Expr = J::Expr;
class Parameter = J::Parameter;
class VariableWrite = J::VariableWrite;
predicate explicitWrite(VariableWrite w, BasicBlock bb, int i, BaseSsaSourceVariable v) {
variableUpdate(v, w.asExpr().getControlFlowNode(), bb, i)
or
exists(Parameter p, Callable c |
c = p.getCallable() and
v = TLocalVar(c, p) and
w.isParameterInit(p) and
c.getBody().getBasicBlock() = bb and
i = -1
)
}
}
module Ssa = Impl::MakeSsa<SsaInput>;
import Ssa
private import Cached private import Cached
cached cached
private module 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
result = v.getAnAccess()
)
}
cached
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Impl::Definition def) {
Impl::ssaDefReachesEndOfBlock(bb, def, _)
}
cached
predicate firstUse(Impl::Definition def, VarRead use) {
exists(BasicBlock bb, int i |
Impl::firstUse(def, bb, i, _) and
use.getControlFlowNode() = bb.getNode(i)
)
}
cached
predicate ssaUpdate(Impl::Definition def, VariableUpdate upd) {
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
variableUpdate(v, upd.getControlFlowNode(), bb, i) and
getDestVar(upd) = v
)
}
cached
predicate ssaImplicitInit(Impl::WriteDefinition def) {
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
hasEntryDef(v, bb) and
i = 0
)
}
/** Holds if `init` is a closure variable that captures the value of `capturedvar`. */ /** Holds if `init` is a closure variable that captures the value of `capturedvar`. */
cached cached
predicate captures(BaseSsaImplicitInit init, BaseSsaVariable capturedvar) { predicate captures(SsaImplicitEntryDefinition init, SsaDefinition capturedvar) {
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
Impl::ssaDefReachesRead(_, capturedvar, bb, i) and Ssa::ssaDefReachesUncertainRead(_, capturedvar, bb, i) and
variableCapture(capturedvar.getSourceVariable(), init.getSourceVariable(), bb, i) variableCapture(capturedvar.getSourceVariable(), init.getSourceVariable(), bb, i)
) )
} }
cached
predicate phiHasInputFromBlock(Impl::PhiNode phi, Impl::Definition inp, BasicBlock bb) {
Impl::phiHasInputFromBlock(phi, inp, bb)
}
cached cached
module SsaPublic { module SsaPublic {
/** /**
@@ -285,36 +265,73 @@ private module Cached {
import SsaPublic import SsaPublic
/** /** An SSA definition in a closure that captures a variable. */
* An SSA variable. class SsaCapturedDefinition extends SsaImplicitEntryDefinition {
*/ SsaCapturedDefinition() { captures(this, _) }
class BaseSsaVariable extends Impl::Definition {
/** Gets the `ControlFlowNode` at which this SSA variable is defined. */
ControlFlowNode getCfgNode() {
exists(BasicBlock bb, int i | this.definesAt(_, bb, i) and result = bb.getNode(0.maximum(i)))
}
/** Gets an access of this SSA variable. */ override string toString() { result = "SSA capture def(" + this.getSourceVariable() + ")" }
VarRead getAUse() { result = getAUse(this) }
/** Holds if this definition captures the value of `capturedvar`. */
predicate captures(SsaDefinition capturedvar) { captures(this, capturedvar) }
/** /**
* Gets an access of the SSA source variable underlying this SSA variable * Gets a definition that ultimately defines the captured variable and is not itself a phi node.
* that can be reached from this SSA variable without passing through any
* other uses, but potentially through phi nodes.
*
* Subsequent uses can be found by following the steps defined by
* `baseSsaAdjacentUseUse`.
*/ */
VarRead getAFirstUse() { firstUse(this, result) } SsaDefinition getAnUltimateCapturedDefinition() {
exists(SsaDefinition capturedvar |
captures(this, capturedvar) and result = capturedvar.getAnUltimateDefinition()
)
}
}
deprecated private predicate ssaUpdate(Impl::Definition def, VariableUpdate upd) {
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
variableUpdate(v, upd.getControlFlowNode(), bb, i) and
getDestVar(upd) = v
)
}
deprecated private predicate ssaImplicitInit(Impl::WriteDefinition def) {
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
hasEntryDef(v, bb) and
i = -1
)
}
/**
* DEPRECATED: Use `SsaDefinition` instead.
*
* An SSA variable.
*/
deprecated class BaseSsaVariable extends Impl::Definition {
/**
* DEPRECATED: Use `getControlFlowNode()` instead.
*
* Gets the `ControlFlowNode` at which this SSA variable is defined.
*/
deprecated ControlFlowNode getCfgNode() { result = this.(SsaDefinition).getControlFlowNode() }
/**
* DEPRECATED: Use `getARead()` instead.
*
* Gets an access of this SSA variable.
*/
deprecated VarRead getAUse() { result = this.(SsaDefinition).getARead() }
/** Holds if this SSA variable is live at the end of `b`. */ /** Holds if this SSA variable is live at the end of `b`. */
predicate isLiveAtEndOfBlock(BasicBlock b) { ssaDefReachesEndOfBlock(b, this) } predicate isLiveAtEndOfBlock(BasicBlock b) { this.(SsaDefinition).isLiveAtEndOfBlock(b) }
/** Gets an input to the phi node defining the SSA variable. */ /** Gets an input to the phi node defining the SSA variable. */
private BaseSsaVariable getAPhiInput() { result = this.(BaseSsaPhiNode).getAPhiInput() } private BaseSsaVariable getAPhiInput() { result = this.(BaseSsaPhiNode).getAnInput() }
/** Gets a definition in the same callable that ultimately defines this variable and is not itself a phi node. */ /**
BaseSsaVariable getAnUltimateLocalDefinition() { * DEPRECATED: Use `SsaDefinition::getAnUltimateDefinition()` instead.
*
* Gets a definition in the same callable that ultimately defines this variable and is not itself a phi node.
*/
deprecated BaseSsaVariable getAnUltimateLocalDefinition() {
result = this.getAPhiInput*() and not result instanceof BaseSsaPhiNode result = this.getAPhiInput*() and not result instanceof BaseSsaPhiNode
} }
@@ -324,18 +341,27 @@ class BaseSsaVariable extends Impl::Definition {
* variable. * variable.
*/ */
private BaseSsaVariable getAPhiInputOrCapturedVar() { private BaseSsaVariable getAPhiInputOrCapturedVar() {
result = this.(BaseSsaPhiNode).getAPhiInput() or result = this.(BaseSsaPhiNode).getAnInput() or
this.(BaseSsaImplicitInit).captures(result) this.(BaseSsaImplicitInit).captures(result)
} }
/** Gets a definition that ultimately defines this variable and is not itself a phi node. */ /**
BaseSsaVariable getAnUltimateDefinition() { * DEPRECATED: Use `SsaCapturedDefinition::getAnUltimateCapturedDefinition()`
* and/or `SsaDefinition::getAnUltimateDefinition()` instead.
*
* Gets a definition that ultimately defines this variable and is not itself a phi node.
*/
deprecated BaseSsaVariable getAnUltimateDefinition() {
result = this.getAPhiInputOrCapturedVar*() and not result instanceof BaseSsaPhiNode result = this.getAPhiInputOrCapturedVar*() and not result instanceof BaseSsaPhiNode
} }
} }
/** An SSA variable that is defined by a `VariableUpdate`. */ /**
class BaseSsaUpdate extends BaseSsaVariable instanceof Impl::WriteDefinition { * DEPRECATED: Use `SsaExplicitWrite` instead.
*
* An SSA variable that is defined by a `VariableUpdate`.
*/
deprecated class BaseSsaUpdate extends BaseSsaVariable instanceof Impl::WriteDefinition {
BaseSsaUpdate() { ssaUpdate(this, _) } BaseSsaUpdate() { ssaUpdate(this, _) }
/** Gets the `VariableUpdate` defining the SSA variable. */ /** Gets the `VariableUpdate` defining the SSA variable. */
@@ -343,34 +369,46 @@ class BaseSsaUpdate extends BaseSsaVariable instanceof Impl::WriteDefinition {
} }
/** /**
* DEPRECATED: Use `SsaParameterInit` or `SsaCapturedDefinition` instead.
*
* An SSA variable that is defined by its initial value in the callable. This * An SSA variable that is defined by its initial value in the callable. This
* includes initial values of parameters, fields, and closure variables. * includes initial values of parameters, fields, and closure variables.
*/ */
class BaseSsaImplicitInit extends BaseSsaVariable instanceof Impl::WriteDefinition { deprecated class BaseSsaImplicitInit extends BaseSsaVariable instanceof Impl::WriteDefinition {
BaseSsaImplicitInit() { ssaImplicitInit(this) } BaseSsaImplicitInit() { ssaImplicitInit(this) }
/** Holds if this is a closure variable that captures the value of `capturedvar`. */ /** Holds if this is a closure variable that captures the value of `capturedvar`. */
predicate captures(BaseSsaVariable capturedvar) { captures(this, capturedvar) } predicate captures(BaseSsaVariable capturedvar) { captures(this, capturedvar) }
/** /**
* DEPRECATED: Use `SsaParameterInit::getParameter()` instead.
*
* Holds if the SSA variable is a parameter defined by its initial value in the callable. * Holds if the SSA variable is a parameter defined by its initial value in the callable.
*/ */
predicate isParameterDefinition(Parameter p) { deprecated predicate isParameterDefinition(Parameter p) {
this.getSourceVariable() = TLocalVar(p.getCallable(), p) and this.getSourceVariable() = TLocalVar(p.getCallable(), p) and
p.getCallable().getBody().getControlFlowNode() = this.getCfgNode() p.getCallable().getBody().getControlFlowNode() = this.getCfgNode()
} }
} }
/** An SSA phi node. */ /**
class BaseSsaPhiNode extends BaseSsaVariable instanceof Impl::PhiNode { * DEPRECATED: Use `SsaPhiDefinition` instead.
/** Gets an input to the phi node defining the SSA variable. */ *
BaseSsaVariable getAPhiInput() { this.hasInputFromBlock(result, _) } * An SSA phi node.
*/
deprecated class BaseSsaPhiNode extends BaseSsaVariable instanceof Impl::PhiNode {
/**
* DEPRECATED: Use `getAnInput()` instead.
*
* Gets an input to the phi node defining the SSA variable.
*/
deprecated BaseSsaVariable getAPhiInput() { this.hasInputFromBlock(result, _) }
/** Gets an input to the phi node defining the SSA variable. */ /** Gets an input to the phi node defining the SSA variable. */
BaseSsaVariable getAnInput() { this.hasInputFromBlock(result, _) } BaseSsaVariable getAnInput() { this.hasInputFromBlock(result, _) }
/** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */ /** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */
predicate hasInputFromBlock(BaseSsaVariable inp, BasicBlock bb) { predicate hasInputFromBlock(BaseSsaVariable inp, BasicBlock bb) {
phiHasInputFromBlock(this, inp, bb) this.(SsaPhiDefinition).hasInputFromBlock(inp, bb)
} }
} }

View File

@@ -460,12 +460,12 @@ predicate arrayStoreStep(Node node1, Node node2) {
} }
private predicate enhancedForStmtStep(Node node1, Node node2, Type containerType) { private predicate enhancedForStmtStep(Node node1, Node node2, Type containerType) {
exists(EnhancedForStmt for, Expr e, SsaExplicitUpdate v | exists(EnhancedForStmt for, Expr e, SsaExplicitWrite v |
for.getExpr() = e and for.getExpr() = e and
node1.asExpr() = e and node1.asExpr() = e and
containerType = e.getType() and containerType = e.getType() and
v.getDefiningExpr() = for.getVariable() and v.getDefiningExpr() = for.getVariable() and
v.getAFirstUse() = node2.asExpr() ssaGetAFirstUse(v) = node2.asExpr()
) )
} }

View File

@@ -29,7 +29,7 @@ private predicate deadcode(Expr e) {
module SsaFlow { module SsaFlow {
module Impl = SsaImpl::DataFlowIntegration; module Impl = SsaImpl::DataFlowIntegration;
private predicate ssaDefAssigns(SsaExplicitUpdate def, Expr value) { private predicate ssaDefAssigns(SsaExplicitWrite def, Expr value) {
exists(VariableUpdate upd | upd = def.getDefiningExpr() | exists(VariableUpdate upd | upd = def.getDefiningExpr() |
value = upd.(VariableAssign).getSource() or value = upd.(VariableAssign).getSource() or
value = upd.(AssignOp) or value = upd.(AssignOp) or
@@ -46,7 +46,7 @@ module SsaFlow {
or or
exists(Parameter p | exists(Parameter p |
n = TExplicitParameterNode(p) and n = TExplicitParameterNode(p) and
result.(Impl::WriteDefSourceNode).getDefinition().(SsaImplicitInit).isParameterDefinition(p) result.(Impl::WriteDefSourceNode).getDefinition().(SsaParameterInit).getParameter() = p
) )
or or
ssaDefAssigns(result.(Impl::WriteDefSourceNode).getDefinition(), n.asExpr()) ssaDefAssigns(result.(Impl::WriteDefSourceNode).getDefinition(), n.asExpr())

View File

@@ -62,10 +62,10 @@ private predicate fieldStep(Node node1, Node node2) {
private predicate closureFlowStep(Expr e1, Expr e2) { private predicate closureFlowStep(Expr e1, Expr e2) {
simpleAstFlowStep(e1, e2) simpleAstFlowStep(e1, e2)
or or
exists(SsaVariable v | exists(SsaDefinition v, SsaExplicitWrite def | v.getARead() = e2 and def.getValue() = e1 |
v.getAUse() = e2 and v.getAnUltimateDefinition() = def
v.getAnUltimateDefinition().(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = or
e1 v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def
) )
} }
@@ -395,13 +395,13 @@ class CastNode extends ExprNode {
CastNode() { CastNode() {
this.getExpr() instanceof CastingExpr this.getExpr() instanceof CastingExpr
or or
exists(SsaExplicitUpdate upd | exists(SsaExplicitWrite upd |
upd.getDefiningExpr().(VariableAssign).getSource() = upd.getDefiningExpr().(VariableAssign).getSource() =
[ [
any(SwitchStmt ss).getExpr(), any(SwitchExpr se).getExpr(), any(SwitchStmt ss).getExpr(), any(SwitchExpr se).getExpr(),
any(InstanceOfExpr ioe).getExpr() any(InstanceOfExpr ioe).getExpr()
] and ] and
this.asExpr() = upd.getAFirstUse() this.asExpr() = ssaGetAFirstUse(upd)
) )
} }
} }
@@ -531,9 +531,9 @@ class NodeRegion instanceof BasicBlock {
private predicate constantBooleanExpr(Expr e, boolean val) { private predicate constantBooleanExpr(Expr e, boolean val) {
e.(CompileTimeConstantExpr).getBooleanValue() = val e.(CompileTimeConstantExpr).getBooleanValue() = val
or or
exists(SsaExplicitUpdate v, Expr src | exists(SsaExplicitWrite v, Expr src |
e = v.getAUse() and e = v.getARead() and
src = v.getDefiningExpr().(VariableAssign).getSource() and src = v.getValue() and
constantBooleanExpr(src, val) constantBooleanExpr(src, val)
) )
} }
@@ -551,15 +551,15 @@ private class ConstantBooleanArgumentNode extends ArgumentNode, ExprNode {
*/ */
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) {
exists( exists(
ExplicitParameterNode paramNode, ConstantBooleanArgumentNode arg, SsaImplicitInit param, ExplicitParameterNode paramNode, ConstantBooleanArgumentNode arg, SsaParameterInit param,
Guard guard Guard guard
| |
// get constant bool argument and parameter for this call // get constant bool argument and parameter for this call
viableParamArg(call, pragma[only_bind_into](paramNode), arg) and viableParamArg(call, pragma[only_bind_into](paramNode), arg) and
// get the ssa variable definition for this parameter // get the ssa variable definition for this parameter
param.isParameterDefinition(paramNode.getParameter()) and param.getParameter() = paramNode.getParameter() and
// which is used in a guard // which is used in a guard
param.getAUse() = guard and param.getARead() = guard and
// which controls `n` with the opposite value of `arg` // which controls `n` with the opposite value of `arg`
guard guard
.controls(nr, .controls(nr,

View File

@@ -99,11 +99,12 @@ predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)
* updates. * updates.
*/ */
predicate hasNonlocalValue(FieldRead fr) { predicate hasNonlocalValue(FieldRead fr) {
not exists(SsaVariable v | v.getAUse() = fr) not exists(SsaDefinition v | v.getARead() = fr)
or or
exists(SsaVariable v, SsaVariable def | v.getAUse() = fr and def = v.getAnUltimateDefinition() | exists(SsaDefinition v, SsaDefinition def |
def instanceof SsaImplicitInit or v.getARead() = fr and
def instanceof SsaImplicitUpdate def = v.getAnUltimateDefinition() and
def instanceof SsaImplicitWrite
) )
} }

View File

@@ -82,13 +82,6 @@ private module TrackedVariablesImpl {
private import TrackedVariablesImpl private import TrackedVariablesImpl
private predicate untrackedFieldWrite(BasicBlock bb, int i, SsaSourceVariable v) {
v =
any(SsaSourceField nf |
bb.getNode(i + 1) = nf.getAnAccess().(FieldRead).getControlFlowNode() and not trackField(nf)
)
}
/** Gets the definition point of a nested class in the parent scope. */ /** Gets the definition point of a nested class in the parent scope. */
private ControlFlowNode parentDef(NestedClass nc) { private ControlFlowNode parentDef(NestedClass nc) {
nc.(AnonymousClass).getClassInstanceExpr().getControlFlowNode() = result or nc.(AnonymousClass).getClassInstanceExpr().getControlFlowNode() = result or
@@ -171,7 +164,7 @@ private predicate uncertainVariableUpdateImpl(TrackedVar v, ControlFlowNode n, B
predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) = predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) =
forceLocal(uncertainVariableUpdateImpl/4)(v, n, b, i) forceLocal(uncertainVariableUpdateImpl/4)(v, n, b, i)
private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> { private module SsaImplInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
class SourceVariable = SsaSourceVariable; class SourceVariable = SsaSourceVariable;
/** /**
@@ -184,11 +177,8 @@ private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock>
certainVariableUpdate(v, _, bb, i) and certainVariableUpdate(v, _, bb, i) and
certain = true certain = true
or or
untrackedFieldWrite(bb, i, v) and
certain = true
or
hasEntryDef(v, bb) and hasEntryDef(v, bb) and
i = 0 and i = -1 and
certain = true certain = true
or or
uncertainVariableUpdate(v, _, bb, i) and uncertainVariableUpdate(v, _, bb, i) and
@@ -204,7 +194,10 @@ private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock>
hasDominanceInformation(bb) and hasDominanceInformation(bb) and
( (
exists(VarRead use | exists(VarRead use |
v.getAnAccess() = use and bb.getNode(i) = use.getControlFlowNode() and certain = true v instanceof TrackedVar and
v.getAnAccess() = use and
bb.getNode(i) = use.getControlFlowNode() and
certain = true
) )
or or
variableCapture(v, _, bb, i) and variableCapture(v, _, bb, i) and
@@ -213,7 +206,35 @@ private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock>
} }
} }
import SsaImplCommon::Make<Location, Cfg, SsaInput> as Impl import SsaImplCommon::Make<Location, Cfg, SsaImplInput> as Impl
private module SsaInput implements Impl::SsaInputSig {
private import java as J
class Expr = J::Expr;
class Parameter = J::Parameter;
class VariableWrite = J::VariableWrite;
predicate explicitWrite(VariableWrite w, BasicBlock bb, int i, SsaSourceVariable v) {
exists(VariableUpdate upd |
upd = w.asExpr() and
certainVariableUpdate(v, upd.getControlFlowNode(), bb, i) and
getDestVar(upd) = v
)
or
exists(Parameter p, Callable c |
c = p.getCallable() and
v = TLocalVar(c, p) and
w.isParameterInit(p) and
c.getBody().getBasicBlock() = bb and
i = -1
)
}
}
module Ssa = Impl::MakeSsa<SsaInput>;
final class Definition = Impl::Definition; final class Definition = Impl::Definition;
@@ -223,14 +244,51 @@ final class UncertainWriteDefinition = Impl::UncertainWriteDefinition;
final class PhiNode = Impl::PhiNode; final class PhiNode = Impl::PhiNode;
class UntrackedDef extends Definition { predicate ssaExplicitUpdate(SsaUpdate def, VariableUpdate upd) {
private VarRead read; exists(SsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
certainVariableUpdate(v, upd.getControlFlowNode(), bb, i) and
getDestVar(upd) = def.getSourceVariable()
)
}
UntrackedDef() { ssaUntrackedDef(this, read) } deprecated predicate ssaUncertainImplicitUpdate(SsaImplicitUpdate def) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
uncertainVariableUpdate(v, _, bb, i)
)
}
string toString() { result = read.toString() } predicate ssaImplicitInit(WriteDefinition def) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
hasEntryDef(v, bb) and
i = -1
)
}
Location getLocation() { result = read.getLocation() } /**
* Holds if the SSA definition of `v` at `def` reaches `redef` without crossing another
* SSA definition of `v`.
*/
deprecated predicate ssaDefReachesUncertainDef(TrackedSsaDef def, SsaUncertainImplicitUpdate redef) {
Impl::uncertainWriteDefinitionInput(redef, def)
}
VarRead getAUse(Definition def) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
Impl::ssaDefReachesRead(v, def, bb, i) and
result.getControlFlowNode() = bb.getNode(i) and
result = v.getAnAccess()
)
}
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def) {
Impl::ssaDefReachesEndOfBlock(bb, def, _)
}
deprecated predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
Impl::phiHasInputFromBlock(phi, inp, bb)
} }
cached cached
@@ -247,24 +305,6 @@ private module Cached {
result.getAnAccess() = upd.(UnaryAssignExpr).getExpr() result.getAnAccess() = upd.(UnaryAssignExpr).getExpr()
} }
cached
predicate ssaExplicitUpdate(SsaUpdate def, VariableUpdate upd) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
certainVariableUpdate(v, upd.getControlFlowNode(), bb, i) and
getDestVar(upd) = def.getSourceVariable()
)
}
cached
predicate ssaUntrackedDef(Definition def, VarRead read) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
untrackedFieldWrite(bb, i, v) and
read.getControlFlowNode() = bb.getNode(i + 1)
)
}
/* /*
* The SSA construction for a field `f` relies on implicit update nodes at * The SSA construction for a field `f` relies on implicit update nodes at
* every call site that conceivably could reach an update of the field. * every call site that conceivably could reach an update of the field.
@@ -484,46 +524,20 @@ private module Cached {
overlay[global] overlay[global]
cached cached
predicate defUpdatesNamedField(SsaImplicitUpdate def, TrackedField f, Callable setter) { predicate defUpdatesNamedField(SsaImplicitWrite calldef, TrackedField f, Callable setter) {
f = def.getSourceVariable() and f = calldef.getSourceVariable() and
updatesNamedField0(def.getCfgNode().asCall(), f, setter) updatesNamedField0(calldef.getControlFlowNode().asCall(), f, setter)
}
cached
predicate ssaUncertainImplicitUpdate(SsaImplicitUpdate def) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
uncertainVariableUpdate(v, _, bb, i)
)
}
cached
predicate ssaImplicitInit(WriteDefinition def) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
def.definesAt(v, bb, i) and
hasEntryDef(v, bb) and
i = 0
)
} }
/** Holds if `init` is a closure variable that captures the value of `capturedvar`. */ /** Holds if `init` is a closure variable that captures the value of `capturedvar`. */
cached cached
predicate captures(SsaImplicitInit init, SsaVariable capturedvar) { predicate captures(SsaImplicitEntryDefinition init, SsaDefinition capturedvar) {
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
Impl::ssaDefReachesRead(_, capturedvar, bb, i) and Ssa::ssaDefReachesUncertainRead(_, capturedvar, bb, i) and
variableCapture(capturedvar.getSourceVariable(), init.getSourceVariable(), bb, i) variableCapture(capturedvar.getSourceVariable(), init.getSourceVariable(), bb, i)
) )
} }
/**
* Holds if the SSA definition of `v` at `def` reaches `redef` without crossing another
* SSA definition of `v`.
*/
cached
predicate ssaDefReachesUncertainDef(TrackedSsaDef def, SsaUncertainImplicitUpdate redef) {
Impl::uncertainWriteDefinitionInput(redef, def)
}
/** /**
* Holds if the value defined at `def` can reach `use` without passing through * Holds if the value defined at `def` can reach `use` without passing through
* any other uses, but possibly through phi nodes and uncertain implicit updates. * any other uses, but possibly through phi nodes and uncertain implicit updates.
@@ -536,25 +550,6 @@ private module Cached {
) )
} }
cached
VarRead getAUse(Definition def) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
Impl::ssaDefReachesRead(v, def, bb, i) and
result.getControlFlowNode() = bb.getNode(i) and
result = v.getAnAccess()
)
}
cached
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def) {
Impl::ssaDefReachesEndOfBlock(bb, def, _)
}
cached
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
Impl::phiHasInputFromBlock(phi, inp, bb)
}
cached cached
module DataFlowIntegration { module DataFlowIntegration {
import DataFlowIntegrationImpl import DataFlowIntegrationImpl
@@ -664,14 +659,12 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
} }
} }
Expr getARead(Definition def) { result = getAUse(def) } Expr getARead(Definition def) { result = def.(SsaDefinition).getARead() }
predicate ssaDefHasSource(WriteDefinition def) { predicate ssaDefHasSource(WriteDefinition def) { def instanceof SsaExplicitWrite }
def instanceof SsaExplicitUpdate or def.(SsaImplicitInit).isParameterDefinition(_)
}
predicate allowFlowIntoUncertainDef(UncertainWriteDefinition def) { predicate allowFlowIntoUncertainDef(UncertainWriteDefinition def) {
def instanceof SsaUncertainImplicitUpdate def instanceof SsaUncertainWrite
} }
class GuardValue = Guards::GuardValue; class GuardValue = Guards::GuardValue;

View File

@@ -8,7 +8,9 @@ private import java as J
private import semmle.code.java.dataflow.SSA as Ssa private import semmle.code.java.dataflow.SSA as Ssa
private import semmle.code.java.dataflow.RangeUtils as RU private import semmle.code.java.dataflow.RangeUtils as RU
class SsaVariable = Ssa::SsaVariable; class SsaVariable extends Ssa::SsaDefinition {
Expr getAUse() { result = super.getARead() }
}
class Expr = J::Expr; class Expr = J::Expr;

View File

@@ -11,9 +11,11 @@ module Private {
class BasicBlock = BB::BasicBlock; class BasicBlock = BB::BasicBlock;
class SsaVariable = Ssa::SsaVariable; class SsaVariable extends Ssa::SsaDefinition {
Expr getAUse() { result = super.getARead() }
}
class SsaPhiNode = Ssa::SsaPhiNode; class SsaPhiNode = Ssa::SsaPhiDefinition;
class Expr = J::Expr; class Expr = J::Expr;

View File

@@ -17,9 +17,9 @@ module Private {
class Guard = G::Guards_v2::Guard; class Guard = G::Guards_v2::Guard;
class SsaVariable = Ssa::SsaVariable; class SsaVariable = Ssa::SsaDefinition;
class SsaPhiNode = Ssa::SsaPhiNode; class SsaPhiNode = Ssa::SsaPhiDefinition;
class VarAccess = J::VarAccess; class VarAccess = J::VarAccess;
@@ -240,8 +240,8 @@ private module Impl {
} }
/** Returns the underlying variable update of the explicit SSA variable `v`. */ /** Returns the underlying variable update of the explicit SSA variable `v`. */
VariableUpdate getExplicitSsaAssignment(SsaVariable v) { VariableUpdate getExplicitSsaAssignment(SsaDefinition v) {
result = v.(SsaExplicitUpdate).getDefiningExpr() result = v.(SsaExplicitWrite).getDefiningExpr()
} }
/** Returns the assignment of the variable update `def`. */ /** Returns the assignment of the variable update `def`. */
@@ -267,13 +267,12 @@ private module Impl {
} }
/** Gets the variable underlying the implicit SSA variable `v`. */ /** Gets the variable underlying the implicit SSA variable `v`. */
Variable getImplicitSsaDeclaration(SsaVariable v) { Variable getImplicitSsaDeclaration(SsaDefinition v) {
result = v.(SsaImplicitUpdate).getSourceVariable().getVariable() or result = v.(SsaImplicitWrite).getSourceVariable().getVariable()
result = v.(SsaImplicitInit).getSourceVariable().getVariable()
} }
/** Holds if the variable underlying the implicit SSA variable `v` is not a field. */ /** Holds if the variable underlying the implicit SSA variable `v` is not a field. */
predicate nonFieldImplicitSsaDefinition(SsaImplicitInit v) { v.isParameterDefinition(_) } predicate nonFieldImplicitSsaDefinition(SsaParameterInit v) { any() }
/** Returned an expression that is assigned to `f`. */ /** Returned an expression that is assigned to `f`. */
Expr getAssignedValueToField(Field f) { Expr getAssignedValueToField(Field f) {
@@ -324,7 +323,7 @@ private module Impl {
result = e.(CastingExpr).getExpr() result = e.(CastingExpr).getExpr()
} }
Expr getARead(SsaVariable v) { result = v.getAUse() } Expr getARead(SsaDefinition v) { result = v.getARead() }
Field getField(FieldAccess fa) { result = fa.getField() } Field getField(FieldAccess fa) { result = fa.getField() }

View File

@@ -8,14 +8,14 @@ private import semmle.code.java.dataflow.SSA as Ssa
private import semmle.code.java.controlflow.BasicBlocks as BB private import semmle.code.java.controlflow.BasicBlocks as BB
private import SsaReadPositionCommon private import SsaReadPositionCommon
class SsaVariable = Ssa::SsaVariable; class SsaVariable = Ssa::SsaDefinition;
class SsaPhiNode = Ssa::SsaPhiNode; class SsaPhiNode = Ssa::SsaPhiDefinition;
class BasicBlock = BB::BasicBlock; class BasicBlock = BB::BasicBlock;
/** Gets a basic block in which SSA variable `v` is read. */ /** Gets a basic block in which SSA variable `v` is read. */
BasicBlock getAReadBasicBlock(SsaVariable v) { result = v.getAUse().getBasicBlock() } BasicBlock getAReadBasicBlock(SsaVariable v) { result = v.getARead().getBasicBlock() }
private predicate id(BB::ExprParent x, BB::ExprParent y) { x = y } private predicate id(BB::ExprParent x, BB::ExprParent y) { x = y }

View File

@@ -8,7 +8,7 @@
import java import java
private import VirtualDispatch private import VirtualDispatch
private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.dataflow.internal.BaseSSA as Base
private import semmle.code.java.dataflow.internal.DataFlowUtil as DataFlow private import semmle.code.java.dataflow.internal.DataFlowUtil as DataFlow
private import semmle.code.java.dataflow.internal.DataFlowPrivate as DataFlowPrivate private import semmle.code.java.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import semmle.code.java.dataflow.InstanceAccess private import semmle.code.java.dataflow.InstanceAccess
@@ -162,14 +162,28 @@ private module TypeTrackingSteps {
storeContents = loadContents storeContents = loadContents
} }
predicate simpleLocalSmallStep(Node n1, Node n2) { /**
exists(BaseSsaVariable v, BaseSsaVariable def | * Holds if `n` is a read of an SSA variable that is ultimately defined by `def`.
def.(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr() *
or * This includes reads of captured variables even though they are not technically
def.(BaseSsaImplicitInit).isParameterDefinition(n1.asParameter()) * local steps, but treating them as local is useful for type tracking purposes.
*/
private predicate readsSsa(Node n, Base::SsaDefinition def) {
exists(Base::SsaDefinition v |
v.getAnUltimateDefinition() = def or
v.(Base::SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def
| |
v.getAnUltimateDefinition() = def and v.getARead() = n.asExpr()
v.getAUse() = n2.asExpr() )
}
predicate simpleLocalSmallStep(Node n1, Node n2) {
exists(Base::SsaDefinition def |
def.(Base::SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
or
def.(Base::SsaParameterInit).getParameter() = n1.asParameter()
|
readsSsa(n2, def)
) )
or or
exists(Callable c | n1.(DataFlow::InstanceParameterNode).getCallable() = c | exists(Callable c | n1.(DataFlow::InstanceParameterNode).getCallable() = c |
@@ -220,11 +234,10 @@ private module TypeTrackingSteps {
n2.asExpr() = get n2.asExpr() = get
) )
or or
exists(EnhancedForStmt for, BaseSsaVariable ssa, BaseSsaVariable def | exists(EnhancedForStmt for, Base::SsaDefinition def |
for.getVariable() = def.(BaseSsaUpdate).getDefiningExpr() and for.getVariable() = def.(Base::SsaExplicitWrite).getDefiningExpr() and
for.getExpr() = v.getAnAccess() and for.getExpr() = v.getAnAccess() and
ssa.getAnUltimateDefinition() = def and readsSsa(n2, def)
ssa.getAUse() = n2.asExpr()
) )
) )
} }
@@ -259,16 +272,15 @@ private module TypeTrackingSteps {
} }
predicate loadStep(Node n1, LocalSourceNode n2, Content f) { predicate loadStep(Node n1, LocalSourceNode n2, Content f) {
exists(BaseSsaVariable v, BaseSsaVariable def | exists(Base::SsaDefinition def |
exists(EnhancedForStmt for | exists(EnhancedForStmt for |
for.getVariable() = def.(BaseSsaUpdate).getDefiningExpr() and for.getVariable() = def.(Base::SsaExplicitWrite).getDefiningExpr() and
for.getExpr() = n1.asExpr() and for.getExpr() = n1.asExpr() and
n1.getType() instanceof Array and n1.getType() instanceof Array and
f = ContentArray() f = ContentArray()
) )
| |
v.getAnUltimateDefinition() = def and readsSsa(n2, def)
v.getAUse() = n2.asExpr()
) )
or or
n2.asExpr().(ArrayAccess).getArray() = n1.asExpr() n2.asExpr().(ArrayAccess).getArray() = n1.asExpr()

View File

@@ -10,7 +10,7 @@
import java import java
private import VirtualDispatch private import VirtualDispatch
private import semmle.code.java.controlflow.Guards private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.dataflow.internal.BaseSSA as Base
private import semmle.code.java.dataflow.internal.DataFlowUtil private import semmle.code.java.dataflow.internal.DataFlowUtil
private import semmle.code.java.dataflow.internal.DataFlowPrivate private import semmle.code.java.dataflow.internal.DataFlowPrivate
private import semmle.code.java.dataflow.internal.ContainerFlow private import semmle.code.java.dataflow.internal.ContainerFlow
@@ -71,21 +71,24 @@ private predicate callFlowStep(Node n1, Node n2) {
* flow, calls, returns, fields, array reads or writes, or container taint steps. * flow, calls, returns, fields, array reads or writes, or container taint steps.
*/ */
private predicate step(Node n1, Node n2) { private predicate step(Node n1, Node n2) {
exists(BaseSsaVariable v, BaseSsaVariable def | exists(Base::SsaDefinition v, Base::SsaDefinition def |
def.(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr() def.(Base::SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
or or
def.(BaseSsaImplicitInit).isParameterDefinition(n1.asParameter()) def.(Base::SsaParameterInit).getParameter() = n1.asParameter()
or or
exists(EnhancedForStmt for | exists(EnhancedForStmt for |
for.getVariable() = def.(BaseSsaUpdate).getDefiningExpr() and for.getVariable() = def.(Base::SsaExplicitWrite).getDefiningExpr() and
for.getExpr() = n1.asExpr() for.getExpr() = n1.asExpr()
) )
| |
v.getAnUltimateDefinition() = def and (
v.getAUse() = n2.asExpr() v.(Base::SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def or
v.getAnUltimateDefinition() = def
) and
v.getARead() = n2.asExpr()
) )
or or
baseSsaAdjacentUseUse(n1.asExpr(), n2.asExpr()) Base::baseSsaAdjacentUseUse(n1.asExpr(), n2.asExpr())
or or
exists(Callable c | n1.(InstanceParameterNode).getCallable() = c | exists(Callable c | n1.(InstanceParameterNode).getCallable() = c |
exists(InstanceAccess ia | exists(InstanceAccess ia |

View File

@@ -7,7 +7,7 @@ import java
import semmle.code.java.dataflow.TypeFlow import semmle.code.java.dataflow.TypeFlow
private import DispatchFlow as DispatchFlow private import DispatchFlow as DispatchFlow
private import ObjFlow as ObjFlow private import ObjFlow as ObjFlow
private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.dataflow.internal.BaseSSA as Base
private import semmle.code.java.controlflow.Guards private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dispatch.internal.Unification private import semmle.code.java.dispatch.internal.Unification
@@ -194,10 +194,10 @@ private module Dispatch {
*/ */
private predicate impossibleDispatchTarget(MethodCall source, Method tgt) { private predicate impossibleDispatchTarget(MethodCall source, Method tgt) {
tgt = viableImpl_v1_cand(source) and tgt = viableImpl_v1_cand(source) and
exists(Guard typeTest, BaseSsaVariable v, Expr q, RefType t | exists(Guard typeTest, Base::SsaDefinition v, Expr q, RefType t |
source.getQualifier() = q and source.getQualifier() = q and
v.getAUse() = q and v.getARead() = q and
typeTest.appliesTypeTest(v.getAUse(), t, false) and typeTest.appliesTypeTest(v.getARead(), t, false) and
guardControls_v1(typeTest, q.getBasicBlock(), false) and guardControls_v1(typeTest, q.getBasicBlock(), false) and
tgt.getDeclaringType().getSourceDeclaration().getASourceSupertype*() = t.getErasure() tgt.getDeclaringType().getSourceDeclaration().getASourceSupertype*() = t.getErasure()
) )

View File

@@ -41,11 +41,13 @@ private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep {
*/ */
private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep { private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) { override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer | exists(
InputStreamRead m, NestedClass wrapper, SsaDefinition captured, SsaCapturedDefinition capturer
|
wrapper.getASourceSupertype+() instanceof TypeInputStream and wrapper.getASourceSupertype+() instanceof TypeInputStream and
m.getDeclaringType() = wrapper and m.getDeclaringType() = wrapper and
capturer.captures(captured) and capturer.captures(captured) and
TaintTracking::localTaint(DataFlow::exprNode(capturer.getAFirstUse()), TaintTracking::localTaint(DataFlow::exprNode(ssaGetAFirstUse(capturer)),
any(DataFlow::PostUpdateNode pun | any(DataFlow::PostUpdateNode pun |
pun.getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() pun.getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess()
)) and )) and
@@ -55,9 +57,9 @@ private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep {
.getASourceSupertype*() .getASourceSupertype*()
.getSourceDeclaration() = wrapper .getSourceDeclaration() = wrapper
| |
n1.asExpr() = captured.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() n1.asExpr() = captured.(SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource()
or or
captured.(SsaImplicitInit).isParameterDefinition(n1.asParameter()) captured.(SsaParameterInit).getParameter() = n1.asParameter()
) )
} }
} }

View File

@@ -262,10 +262,10 @@ private predicate reaches(Expr src, Argument arg) {
any(StartComponentMethodCall ma).getIntentArg() = arg and any(StartComponentMethodCall ma).getIntentArg() = arg and
src = arg src = arg
or or
exists(Expr mid, BaseSsa::BaseSsaVariable ssa, BaseSsa::BaseSsaUpdate upd | exists(Expr mid, BaseSsa::SsaDefinition ssa, BaseSsa::SsaExplicitWrite upd |
reaches(mid, arg) and reaches(mid, arg) and
mid = ssa.getAUse() and mid = ssa.getARead() and
upd = ssa.getAnUltimateLocalDefinition() and upd = ssa.getAnUltimateDefinition() and
src = upd.getDefiningExpr().(VariableAssign).getSource() src = upd.getDefiningExpr().(VariableAssign).getSource()
) )
or or

View File

@@ -38,9 +38,13 @@ private predicate isShell(Expr ex) {
cmd.regexpMatch(".*(sh|javac?|python[23]?|osascript|cmd)(\\.exe)?$") cmd.regexpMatch(".*(sh|javac?|python[23]?|osascript|cmd)(\\.exe)?$")
) )
or or
exists(SsaVariable ssa | exists(SsaDefinition ssa, SsaExplicitWrite def |
ex = ssa.getAUse() and ex = ssa.getARead() and
isShell(ssa.getAnUltimateDefinition().(SsaExplicitUpdate).getDefiningExpr()) isShell(def.getDefiningExpr())
|
ssa.getAnUltimateDefinition() = def
or
ssa.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def
) )
or or
isShell(ex.(Assignment).getRhs()) isShell(ex.(Assignment).getRhs())
@@ -61,17 +65,17 @@ private class ListOfStringType extends CollectionType {
/** /**
* A variable that could be used as a list of arguments to a command. * A variable that could be used as a list of arguments to a command.
*/ */
private class CommandArgumentList extends SsaExplicitUpdate { private class CommandArgumentList extends SsaExplicitWrite {
CommandArgumentList() { CommandArgumentList() {
this.getSourceVariable().getType() instanceof ListOfStringType and this.getSourceVariable().getType() instanceof ListOfStringType and
forex(CollectionMutation ma | ma.getQualifier() = this.getAUse() | forex(CollectionMutation ma | ma.getQualifier() = this.getARead() |
ma.getMethod().getName().matches("add%") ma.getMethod().getName().matches("add%")
) )
} }
/** Gets a use of the variable for which the list could be empty. */ /** Gets a use of the variable for which the list could be empty. */
private VarRead getAUseBeforeFirstAdd() { private VarRead getAUseBeforeFirstAdd() {
result = this.getAFirstUse() result = ssaGetAFirstUse(this)
or or
exists(VarRead mid | exists(VarRead mid |
mid = this.getAUseBeforeFirstAdd() and mid = this.getAUseBeforeFirstAdd() and
@@ -87,7 +91,7 @@ private class CommandArgumentList extends SsaExplicitUpdate {
* Gets an addition to this list, i.e. a call to an `add` or `addAll` method. * Gets an addition to this list, i.e. a call to an `add` or `addAll` method.
*/ */
MethodCall getAnAdd() { MethodCall getAnAdd() {
result.getQualifier() = this.getAUse() and result.getQualifier() = this.getARead() and
result.getMethod().getName().matches("add%") result.getMethod().getName().matches("add%")
} }
@@ -121,10 +125,10 @@ private predicate arrayVarWrite(ArrayAccess acc) { exists(Assignment a | a.getDe
/** /**
* A variable that could be an array of arguments to a command. * A variable that could be an array of arguments to a command.
*/ */
private class CommandArgumentArray extends SsaExplicitUpdate { private class CommandArgumentArray extends SsaExplicitWrite {
CommandArgumentArray() { CommandArgumentArray() {
this.getSourceVariable().getType() instanceof ArrayOfStringType and this.getSourceVariable().getType() instanceof ArrayOfStringType and
forall(ArrayAccess a | a.getArray() = this.getAUse() and arrayVarWrite(a) | forall(ArrayAccess a | a.getArray() = this.getARead() and arrayVarWrite(a) |
a.getIndexExpr() instanceof CompileTimeConstantExpr a.getIndexExpr() instanceof CompileTimeConstantExpr
) )
} }
@@ -133,7 +137,7 @@ private class CommandArgumentArray extends SsaExplicitUpdate {
Expr getAWrite(int index, VarRead use) { Expr getAWrite(int index, VarRead use) {
exists(Assignment a, ArrayAccess acc | exists(Assignment a, ArrayAccess acc |
acc.getArray() = use and acc.getArray() = use and
use = this.getAUse() and use = this.getARead() and
index = acc.getIndexExpr().(CompileTimeConstantExpr).getIntValue() and index = acc.getIndexExpr().(CompileTimeConstantExpr).getIntValue() and
acc = a.getDest() and acc = a.getDest() and
result = a.getRhs() result = a.getRhs()
@@ -150,7 +154,7 @@ private class CommandArgumentArray extends SsaExplicitUpdate {
private class CommandArgArrayImmutableFirst extends CommandArgumentArray { private class CommandArgArrayImmutableFirst extends CommandArgumentArray {
CommandArgArrayImmutableFirst() { CommandArgArrayImmutableFirst() {
(exists(this.getAWrite(0)) or exists(firstElementOf(this.getDefiningExpr()))) and (exists(this.getAWrite(0)) or exists(firstElementOf(this.getDefiningExpr()))) and
forall(VarRead use | exists(this.getAWrite(0, use)) | use = this.getAFirstUse()) forall(VarRead use | exists(this.getAWrite(0, use)) | use = ssaGetAFirstUse(this))
} }
/** Gets the first element of this array. */ /** Gets the first element of this array. */
@@ -173,7 +177,9 @@ private Expr firstElementOf(Expr arr) {
or or
result = firstElementOf(arr.(LocalVariableDeclExpr).getInit()) result = firstElementOf(arr.(LocalVariableDeclExpr).getInit())
or or
exists(CommandArgArrayImmutableFirst caa | arr = caa.getAUse() | result = caa.getFirstElement()) exists(CommandArgArrayImmutableFirst caa | arr = caa.getARead() |
result = caa.getFirstElement()
)
or or
exists(MethodCall ma, Method m | exists(MethodCall ma, Method m |
arr = ma and arr = ma and

View File

@@ -9,7 +9,7 @@ import java
private import codeql.typeflow.UniversalFlow as UniversalFlow private import codeql.typeflow.UniversalFlow as UniversalFlow
private import semmle.code.java.Collections private import semmle.code.java.Collections
private import semmle.code.java.controlflow.Guards private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.dataflow.internal.BaseSSA as Base
private import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.TypeFlow private import semmle.code.java.dataflow.TypeFlow
private import semmle.code.java.dispatch.VirtualDispatch private import semmle.code.java.dispatch.VirtualDispatch
@@ -115,7 +115,7 @@ private predicate nodeWithAddition(FlowNode n, Variable v) {
n.asField() = v n.asField() = v
or or
n.asSsa().getSourceVariable().getVariable() = v and n.asSsa().getSourceVariable().getVariable() = v and
(n.asSsa() instanceof BaseSsaUpdate or n.asSsa().(BaseSsaImplicitInit).isParameterDefinition(_)) n.asSsa() instanceof Base::SsaExplicitWrite
) )
} }

View File

@@ -46,14 +46,14 @@ class RightShiftOp extends Expr {
} }
private predicate boundedRead(VarRead read) { private predicate boundedRead(VarRead read) {
exists(SsaVariable v, ConditionBlock cb, ComparisonExpr comp, boolean testIsTrue | exists(SsaDefinition v, ConditionBlock cb, ComparisonExpr comp, boolean testIsTrue |
read = v.getAUse() and read = v.getARead() and
cb.controls(read.getBasicBlock(), testIsTrue) and cb.controls(read.getBasicBlock(), testIsTrue) and
cb.getCondition() = comp cb.getCondition() = comp
| |
comp.getLesserOperand() = v.getAUse() and testIsTrue = true comp.getLesserOperand() = v.getARead() and testIsTrue = true
or or
comp.getGreaterOperand() = v.getAUse() and testIsTrue = false comp.getGreaterOperand() = v.getARead() and testIsTrue = false
) )
} }

View File

@@ -32,9 +32,9 @@ private predicate validationCall(MethodCall ma, VarAccess va) {
} }
private predicate validatedAccess(VarAccess va) { private predicate validatedAccess(VarAccess va) {
exists(SsaVariable v, MethodCall guardcall | exists(SsaDefinition v, MethodCall guardcall |
va = v.getAUse() and va = v.getARead() and
validationCall(guardcall, v.getAUse()) validationCall(guardcall, v.getARead())
| |
guardcall.(Guard).controls(va.getBasicBlock(), _) guardcall.(Guard).controls(va.getBasicBlock(), _)
or or

View File

@@ -19,10 +19,10 @@ import semmle.code.java.dataflow.RangeUtils
import semmle.code.java.dataflow.RangeAnalysis import semmle.code.java.dataflow.RangeAnalysis
pragma[nomagic] pragma[nomagic]
predicate ssaArrayLengthBound(SsaVariable arr, Bound b) { predicate ssaArrayLengthBound(SsaDefinition arr, Bound b) {
exists(FieldAccess len | exists(FieldAccess len |
len.getField() instanceof ArrayLengthField and len.getField() instanceof ArrayLengthField and
len.getQualifier() = arr.getAUse() and len.getQualifier() = arr.getARead() and
b.getExpr() = len b.getExpr() = len
) )
} }
@@ -31,9 +31,9 @@ predicate ssaArrayLengthBound(SsaVariable arr, Bound b) {
* Holds if the index expression of `aa` is less than or equal to the array length plus `k`. * Holds if the index expression of `aa` is less than or equal to the array length plus `k`.
*/ */
predicate boundedArrayAccess(ArrayAccess aa, int k) { predicate boundedArrayAccess(ArrayAccess aa, int k) {
exists(SsaVariable arr, Expr index, Bound b, int delta | exists(SsaDefinition arr, Expr index, Bound b, int delta |
aa.getIndexExpr() = index and aa.getIndexExpr() = index and
aa.getArray() = arr.getAUse() and aa.getArray() = arr.getARead() and
bounded(index, b, delta, true, _) bounded(index, b, delta, true, _)
| |
ssaArrayLengthBound(arr, b) and ssaArrayLengthBound(arr, b) and

View File

@@ -127,7 +127,7 @@ Expr overFlowCand() {
c.getIntValue() >= 0 c.getIntValue() >= 0
) )
or or
exists(SsaExplicitUpdate x | result = x.getAUse() and x.getDefiningExpr() = overFlowCand()) exists(SsaExplicitWrite x | result = x.getARead() and x.getDefiningExpr() = overFlowCand())
or or
result.(AssignExpr).getRhs() = overFlowCand() result.(AssignExpr).getRhs() = overFlowCand()
or or
@@ -142,27 +142,27 @@ Expr overFlowCand() {
predicate positiveOrNegative(Expr e) { positive(e) or negative(e) } predicate positiveOrNegative(Expr e) { positive(e) or negative(e) }
/** Gets an expression that equals `v` plus a positive or negative value. */ /** Gets an expression that equals `v` plus a positive or negative value. */
Expr increaseOrDecreaseOfVar(SsaVariable v) { Expr increaseOrDecreaseOfVar(SsaDefinition v) {
exists(AssignAddExpr add | exists(AssignAddExpr add |
result = add and result = add and
positiveOrNegative(add.getDest()) and positiveOrNegative(add.getDest()) and
add.getRhs() = v.getAUse() add.getRhs() = v.getARead()
) )
or or
exists(AddExpr add, Expr e | exists(AddExpr add, Expr e |
result = add and result = add and
add.hasOperands(v.getAUse(), e) and add.hasOperands(v.getARead(), e) and
positiveOrNegative(e) positiveOrNegative(e)
) )
or or
exists(SubExpr sub | exists(SubExpr sub |
result = sub and result = sub and
sub.getLeftOperand() = v.getAUse() and sub.getLeftOperand() = v.getARead() and
positiveOrNegative(sub.getRightOperand()) positiveOrNegative(sub.getRightOperand())
) )
or or
exists(SsaExplicitUpdate x | exists(SsaExplicitWrite x |
result = x.getAUse() and x.getDefiningExpr() = increaseOrDecreaseOfVar(v) result = x.getARead() and x.getDefiningExpr() = increaseOrDecreaseOfVar(v)
) )
or or
result.(AssignExpr).getRhs() = increaseOrDecreaseOfVar(v) result.(AssignExpr).getRhs() = increaseOrDecreaseOfVar(v)
@@ -172,7 +172,7 @@ Expr increaseOrDecreaseOfVar(SsaVariable v) {
predicate overFlowTest(ComparisonExpr comp) { predicate overFlowTest(ComparisonExpr comp) {
( (
exists(SsaVariable v | comp.hasOperands(increaseOrDecreaseOfVar(v), v.getAUse())) exists(SsaDefinition v | comp.hasOperands(increaseOrDecreaseOfVar(v), v.getARead()))
or or
comp.getLesserOperand() = overFlowCand() and comp.getLesserOperand() = overFlowCand() and
comp.getGreaterOperand().(IntegerLiteral).getIntValue() = 0 comp.getGreaterOperand().(IntegerLiteral).getIntValue() = 0
@@ -195,9 +195,9 @@ predicate concurrentModificationTest(BinaryExpr test) {
*/ */
pragma[nomagic] pragma[nomagic]
predicate guardedTest(EqualityTest test, Guard guard, boolean isEq, int i1, int i2) { predicate guardedTest(EqualityTest test, Guard guard, boolean isEq, int i1, int i2) {
exists(SsaVariable v, CompileTimeConstantExpr c1, CompileTimeConstantExpr c2 | exists(SsaDefinition v, CompileTimeConstantExpr c1, CompileTimeConstantExpr c2 |
guard.isEquality(v.getAUse(), c1, isEq) and guard.isEquality(v.getARead(), c1, isEq) and
test.hasOperands(v.getAUse(), c2) and test.hasOperands(v.getARead(), c2) and
i1 = c1.getIntValue() and i1 = c1.getIntValue() and
i2 = c2.getIntValue() and i2 = c2.getIntValue() and
v.getSourceVariable().getType() instanceof IntegralType v.getSourceVariable().getType() instanceof IntegralType

View File

@@ -27,14 +27,14 @@ class BoundKind extends string {
*/ */
predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) { predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
exists( exists(
ConditionBlock cb, SsaVariable v, BinaryExpr cond, boolean condIsTrue, int k1, int k2, ConditionBlock cb, SsaDefinition v, BinaryExpr cond, boolean condIsTrue, int k1, int k2,
CompileTimeConstantExpr c1, CompileTimeConstantExpr c2 CompileTimeConstantExpr c1, CompileTimeConstantExpr c2
| |
s1.getCondition() = cond and s1.getCondition() = cond and
cb.getCondition() = cond and cb.getCondition() = cond and
cond.hasOperands(v.getAUse(), c1) and cond.hasOperands(v.getARead(), c1) and
c1.getIntValue() = k1 and c1.getIntValue() = k1 and
test.hasOperands(v.getAUse(), c2) and test.hasOperands(v.getARead(), c2) and
c2.getIntValue() = k2 and c2.getIntValue() = k2 and
v.getSourceVariable().getVariable() instanceof LocalScopeVariable and v.getSourceVariable().getVariable() instanceof LocalScopeVariable and
cb.controls(test.getBasicBlock(), condIsTrue) and cb.controls(test.getBasicBlock(), condIsTrue) and
@@ -49,7 +49,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
) )
or or
exists(ComparisonExpr comp | comp = cond | exists(ComparisonExpr comp | comp = cond |
comp.getLesserOperand() = v.getAUse() and comp.getLesserOperand() = v.getARead() and
( (
condIsTrue = true and condIsTrue = true and
boundKind.isUpper() and boundKind.isUpper() and
@@ -60,7 +60,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
(if comp.isStrict() then bound = k1 else bound = k1 + 1) (if comp.isStrict() then bound = k1 else bound = k1 + 1)
) )
or or
comp.getGreaterOperand() = v.getAUse() and comp.getGreaterOperand() = v.getARead() and
( (
condIsTrue = true and condIsTrue = true and
boundKind.isLower() and boundKind.isLower() and
@@ -88,7 +88,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
) )
or or
exists(ComparisonExpr comp | comp = test | exists(ComparisonExpr comp | comp = test |
comp.getLesserOperand() = v.getAUse() and comp.getLesserOperand() = v.getARead() and
( (
boundKind.providesLowerBound() and boundKind.providesLowerBound() and
testIsTrue = false and testIsTrue = false and
@@ -107,7 +107,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
) )
) )
or or
comp.getGreaterOperand() = v.getAUse() and comp.getGreaterOperand() = v.getARead() and
( (
boundKind.providesLowerBound() and boundKind.providesLowerBound() and
testIsTrue = true and testIsTrue = true and

View File

@@ -8,9 +8,9 @@ import semmle.code.java.dataflow.SSA
private Expr getAFieldRead(Field f) { private Expr getAFieldRead(Field f) {
result = f.getAnAccess() result = f.getAnAccess()
or or
exists(SsaExplicitUpdate v | v.getSourceVariable().getVariable() instanceof LocalScopeVariable | exists(SsaExplicitWrite v | v.getSourceVariable().getVariable() instanceof LocalScopeVariable |
result = v.getAUse() and result = v.getARead() and
v.getDefiningExpr().(VariableAssign).getSource() = getAFieldRead(f) v.getValue() = getAFieldRead(f)
) )
or or
result.(AssignExpr).getSource() = getAFieldRead(f) result.(AssignExpr).getSource() = getAFieldRead(f)

View File

@@ -52,10 +52,10 @@ predicate failedLock(LockType t, BasicBlock lockblock, BasicBlock exblock) {
( (
lock.asExpr() = t.getLockAccess() lock.asExpr() = t.getLockAccess()
or or
exists(SsaExplicitUpdate lockbool | exists(SsaExplicitWrite lockbool |
// Using the value of `t.getLockAccess()` ensures that it is a `tryLock` call. // Using the value of `t.getLockAccess()` ensures that it is a `tryLock` call.
lock.asExpr() = lockbool.getAUse() and lock.asExpr() = lockbool.getARead() and
lockbool.getDefiningExpr().(VariableAssign).getSource() = t.getLockAccess() lockbool.getValue() = t.getLockAccess()
) )
) and ) and
( (

View File

@@ -37,11 +37,11 @@ predicate requiresInstanceOf(Expr e, VarAccess va, RefType t) {
* `v` is not of type `sup`, which is a supertype of `t`. * `v` is not of type `sup`, which is a supertype of `t`.
*/ */
predicate contradictoryTypeCheck(Expr e, Variable v, RefType t, RefType sup, Expr cond) { predicate contradictoryTypeCheck(Expr e, Variable v, RefType t, RefType sup, Expr cond) {
exists(SsaVariable ssa | exists(SsaDefinition ssa |
ssa.getSourceVariable().getVariable() = v and ssa.getSourceVariable().getVariable() = v and
requiresInstanceOf(e, ssa.getAUse(), t) and requiresInstanceOf(e, ssa.getARead(), t) and
sup = t.getAnAncestor() and sup = t.getAnAncestor() and
instanceOfCheck(cond, ssa.getAUse(), sup) and instanceOfCheck(cond, ssa.getARead(), sup) and
cond.(Guard).controls(e.getBasicBlock(), false) and cond.(Guard).controls(e.getBasicBlock(), false) and
not t instanceof ErrorType and not t instanceof ErrorType and
not sup instanceof ErrorType not sup instanceof ErrorType

View File

@@ -75,9 +75,9 @@ where
loopWhileTrue(loop) and loopExitGuard(loop, cond) loopWhileTrue(loop) and loopExitGuard(loop, cond)
) and ) and
// None of the ssa variables in `cond` are updated inside the loop. // None of the ssa variables in `cond` are updated inside the loop.
forex(SsaVariable ssa, VarRead use | ssa.getAUse() = use and use.getParent*() = cond | forex(SsaDefinition ssa, VarRead use | ssa.getARead() = use and use.getParent*() = cond |
not ssa.getCfgNode().getEnclosingStmt().getEnclosingStmt*() = loop or not ssa.getControlFlowNode().getEnclosingStmt().getEnclosingStmt*() = loop or
ssa.getCfgNode().asExpr().getParent*() = loop.(ForStmt).getAnInit() ssa.getControlFlowNode().asExpr().getParent*() = loop.(ForStmt).getAnInit()
) and ) and
// And `cond` does not use method calls, field reads, or array reads. // And `cond` does not use method calls, field reads, or array reads.
not exists(MethodCall ma | ma.getParent*() = cond) and not exists(MethodCall ma | ma.getParent*() = cond) and

View File

@@ -14,7 +14,7 @@ private predicate emptyDecl(LocalVariableDeclExpr decl) {
/** A dead variable update. */ /** A dead variable update. */
predicate deadLocal(VariableUpdate upd) { predicate deadLocal(VariableUpdate upd) {
upd.getDestVar() instanceof LocalScopeVariable and upd.getDestVar() instanceof LocalScopeVariable and
not exists(SsaExplicitUpdate ssa | upd = ssa.getDefiningExpr()) and not exists(SsaExplicitWrite ssa | upd = ssa.getDefiningExpr()) and
not emptyDecl(upd) and not emptyDecl(upd) and
not readImplicitly(upd, _) not readImplicitly(upd, _)
} }

View File

@@ -42,9 +42,9 @@ class CheckSignaturesGuard extends Guard instanceof EqualityTest {
} }
predicate signatureChecked(Expr safe) { predicate signatureChecked(Expr safe) {
exists(CheckSignaturesGuard g, SsaVariable v | exists(CheckSignaturesGuard g, SsaDefinition v |
v.getAUse() = g.getCheckedExpr() and v.getARead() = g.getCheckedExpr() and
safe = v.getAUse() and safe = v.getARead() and
g.controls(safe.getBasicBlock(), g.(EqualityTest).polarity()) g.controls(safe.getBasicBlock(), g.(EqualityTest).polarity())
) )
} }

View File

@@ -277,10 +277,7 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig {
predicate sinkModelSanitizer(DataFlow::Node node) { predicate sinkModelSanitizer(DataFlow::Node node) {
// exclude variable capture jump steps // exclude variable capture jump steps
exists(Ssa::SsaImplicitInit closure | exists(Ssa::SsaCapturedDefinition closure | node.asExpr() = Ssa::ssaGetAFirstUse(closure))
closure.captures(_) and
node.asExpr() = closure.getAFirstUse()
)
} }
predicate apiSource(DataFlow::Node source) { predicate apiSource(DataFlow::Node source) {

View File

@@ -4,24 +4,23 @@
| ModulusAnalysis.java:4:5:4:22 | ...=... | 0 | 43 | 0 | | ModulusAnalysis.java:4:5:4:22 | ...=... | 0 | 43 | 0 |
| ModulusAnalysis.java:4:5:4:22 | c2 | 0 | 43 | 0 | | ModulusAnalysis.java:4:5:4:22 | c2 | 0 | 43 | 0 |
| ModulusAnalysis.java:4:20:4:21 | 43 | 0 | 43 | 0 | | ModulusAnalysis.java:4:20:4:21 | 43 | 0 | 43 | 0 |
| ModulusAnalysis.java:7:13:7:22 | eq | SSA init(i) | 3 | 0 | | ModulusAnalysis.java:7:13:7:22 | eq | SSA param(i) | 3 | 0 |
| ModulusAnalysis.java:7:18:7:18 | i | SSA init(i) | 0 | 0 | | ModulusAnalysis.java:7:18:7:18 | i | SSA param(i) | 0 | 0 |
| ModulusAnalysis.java:7:18:7:22 | ... + ... | SSA init(i) | 3 | 0 | | ModulusAnalysis.java:7:18:7:22 | ... + ... | SSA param(i) | 3 | 0 |
| ModulusAnalysis.java:7:22:7:22 | 3 | 0 | 3 | 0 | | ModulusAnalysis.java:7:22:7:22 | 3 | 0 | 3 | 0 |
| ModulusAnalysis.java:9:13:9:29 | mul | 0 | 3 | 42 | | ModulusAnalysis.java:9:13:9:29 | mul | 0 | 3 | 42 |
| ModulusAnalysis.java:9:19:9:20 | eq | SSA def(eq) | 0 | 0 | | ModulusAnalysis.java:9:19:9:20 | eq | SSA def(eq) | 0 | 0 |
| ModulusAnalysis.java:9:19:9:20 | eq | SSA init(i) | 3 | 0 | | ModulusAnalysis.java:9:19:9:20 | eq | SSA param(i) | 3 | 0 |
| ModulusAnalysis.java:9:19:9:25 | ... * ... | 0 | 0 | 42 | | ModulusAnalysis.java:9:19:9:25 | ... * ... | 0 | 0 | 42 |
| ModulusAnalysis.java:9:19:9:29 | ... + ... | 0 | 3 | 42 | | ModulusAnalysis.java:9:19:9:29 | ... + ... | 0 | 3 | 42 |
| ModulusAnalysis.java:9:24:9:25 | c1 | 0 | 42 | 0 | | ModulusAnalysis.java:9:24:9:25 | c1 | 0 | 42 | 0 |
| ModulusAnalysis.java:9:24:9:25 | c1 | SSA init(this.c1) | 0 | 0 | | ModulusAnalysis.java:9:24:9:25 | c1 | SSA entry def(this.c1) | 0 | 0 |
| ModulusAnalysis.java:9:29:9:29 | 3 | 0 | 3 | 0 | | ModulusAnalysis.java:9:29:9:29 | 3 | 0 | 3 | 0 |
| ModulusAnalysis.java:11:13:11:21 | seven | 0 | 7 | 0 | | ModulusAnalysis.java:11:13:11:21 | seven | 0 | 7 | 0 |
| ModulusAnalysis.java:11:21:11:21 | 7 | 0 | 7 | 0 | | ModulusAnalysis.java:11:21:11:21 | 7 | 0 | 7 | 0 |
| ModulusAnalysis.java:12:13:12:15 | mul | 0 | 3 | 42 | | ModulusAnalysis.java:12:13:12:15 | mul | 0 | 3 | 42 |
| ModulusAnalysis.java:12:13:12:15 | mul | SSA def(mul) | 0 | 0 | | ModulusAnalysis.java:12:13:12:15 | mul | SSA def(mul) | 0 | 0 |
| ModulusAnalysis.java:12:19:12:20 | c2 | 0 | 43 | 0 | | ModulusAnalysis.java:12:19:12:20 | c2 | 0 | 43 | 0 |
| ModulusAnalysis.java:12:19:12:20 | c2 | SSA impl upd[untracked](this.c2) | 0 | 0 |
| ModulusAnalysis.java:12:25:12:29 | seven | 0 | 7 | 0 | | ModulusAnalysis.java:12:25:12:29 | seven | 0 | 7 | 0 |
| ModulusAnalysis.java:12:25:12:29 | seven | SSA def(seven) | 0 | 0 | | ModulusAnalysis.java:12:25:12:29 | seven | SSA def(seven) | 0 | 0 |
| ModulusAnalysis.java:13:32:13:34 | mul | 0 | 3 | 42 | | ModulusAnalysis.java:13:32:13:34 | mul | 0 | 3 | 42 |
@@ -29,49 +28,49 @@
| ModulusAnalysis.java:13:32:13:34 | mul | SSA def(mul) | 0 | 0 | | ModulusAnalysis.java:13:32:13:34 | mul | SSA def(mul) | 0 | 0 |
| ModulusAnalysis.java:16:13:18:23 | j | 0 | 3 | 4 | | ModulusAnalysis.java:16:13:18:23 | j | 0 | 3 | 4 |
| ModulusAnalysis.java:16:17:18:23 | ...?...:... | 0 | 3 | 4 | | ModulusAnalysis.java:16:17:18:23 | ...?...:... | 0 | 3 | 4 |
| ModulusAnalysis.java:17:15:17:15 | i | SSA init(i) | 0 | 0 | | ModulusAnalysis.java:17:15:17:15 | i | SSA param(i) | 0 | 0 |
| ModulusAnalysis.java:17:15:17:19 | ... * ... | 0 | 0 | 4 | | ModulusAnalysis.java:17:15:17:19 | ... * ... | 0 | 0 | 4 |
| ModulusAnalysis.java:17:15:17:23 | ... + ... | 0 | 3 | 4 | | ModulusAnalysis.java:17:15:17:23 | ... + ... | 0 | 3 | 4 |
| ModulusAnalysis.java:17:19:17:19 | 4 | 0 | 4 | 0 | | ModulusAnalysis.java:17:19:17:19 | 4 | 0 | 4 | 0 |
| ModulusAnalysis.java:17:23:17:23 | 3 | 0 | 3 | 0 | | ModulusAnalysis.java:17:23:17:23 | 3 | 0 | 3 | 0 |
| ModulusAnalysis.java:18:15:18:15 | i | SSA init(i) | 0 | 0 | | ModulusAnalysis.java:18:15:18:15 | i | SSA param(i) | 0 | 0 |
| ModulusAnalysis.java:18:15:18:19 | ... * ... | 0 | 0 | 8 | | ModulusAnalysis.java:18:15:18:19 | ... * ... | 0 | 0 | 8 |
| ModulusAnalysis.java:18:15:18:23 | ... + ... | 0 | 7 | 8 | | ModulusAnalysis.java:18:15:18:23 | ... + ... | 0 | 7 | 8 |
| ModulusAnalysis.java:18:19:18:19 | 8 | 0 | 8 | 0 | | ModulusAnalysis.java:18:19:18:19 | 8 | 0 | 8 | 0 |
| ModulusAnalysis.java:18:23:18:23 | 7 | 0 | 7 | 0 | | ModulusAnalysis.java:18:23:18:23 | 7 | 0 | 7 | 0 |
| ModulusAnalysis.java:19:28:19:28 | j | 0 | 3 | 4 | | ModulusAnalysis.java:19:28:19:28 | j | 0 | 3 | 4 |
| ModulusAnalysis.java:19:28:19:28 | j | SSA def(j) | 0 | 0 | | ModulusAnalysis.java:19:28:19:28 | j | SSA def(j) | 0 | 0 |
| ModulusAnalysis.java:21:13:21:13 | x | SSA init(x) | 0 | 0 | | ModulusAnalysis.java:21:13:21:13 | x | SSA param(x) | 0 | 0 |
| ModulusAnalysis.java:21:17:21:18 | c1 | 0 | 42 | 0 | | ModulusAnalysis.java:21:17:21:18 | c1 | 0 | 42 | 0 |
| ModulusAnalysis.java:21:17:21:18 | c1 | SSA init(this.c1) | 0 | 0 | | ModulusAnalysis.java:21:17:21:18 | c1 | SSA entry def(this.c1) | 0 | 0 |
| ModulusAnalysis.java:21:23:21:23 | 3 | 0 | 3 | 0 | | ModulusAnalysis.java:21:23:21:23 | 3 | 0 | 3 | 0 |
| ModulusAnalysis.java:21:28:21:28 | y | SSA init(y) | 0 | 0 | | ModulusAnalysis.java:21:28:21:28 | y | SSA param(y) | 0 | 0 |
| ModulusAnalysis.java:21:32:21:33 | c1 | 0 | 42 | 0 | | ModulusAnalysis.java:21:32:21:33 | c1 | 0 | 42 | 0 |
| ModulusAnalysis.java:21:32:21:33 | c1 | SSA init(this.c1) | 0 | 0 | | ModulusAnalysis.java:21:32:21:33 | c1 | SSA entry def(this.c1) | 0 | 0 |
| ModulusAnalysis.java:21:38:21:38 | 7 | 0 | 7 | 0 | | ModulusAnalysis.java:21:38:21:38 | 7 | 0 | 7 | 0 |
| ModulusAnalysis.java:22:32:22:32 | x | 0 | 3 | 42 | | ModulusAnalysis.java:22:32:22:32 | x | 0 | 3 | 42 |
| ModulusAnalysis.java:22:32:22:32 | x | SSA init(x) | 0 | 0 | | ModulusAnalysis.java:22:32:22:32 | x | SSA param(x) | 0 | 0 |
| ModulusAnalysis.java:22:32:22:36 | ... + ... | 0 | 10 | 42 | | ModulusAnalysis.java:22:32:22:36 | ... + ... | 0 | 10 | 42 |
| ModulusAnalysis.java:22:32:22:36 | ... + ... | SSA init(x) | 7 | 42 | | ModulusAnalysis.java:22:32:22:36 | ... + ... | SSA param(x) | 7 | 42 |
| ModulusAnalysis.java:22:32:22:36 | ... + ... | SSA init(y) | 3 | 42 | | ModulusAnalysis.java:22:32:22:36 | ... + ... | SSA param(y) | 3 | 42 |
| ModulusAnalysis.java:22:36:22:36 | y | 0 | 7 | 42 | | ModulusAnalysis.java:22:36:22:36 | y | 0 | 7 | 42 |
| ModulusAnalysis.java:22:36:22:36 | y | SSA init(y) | 0 | 0 | | ModulusAnalysis.java:22:36:22:36 | y | SSA param(y) | 0 | 0 |
| ModulusAnalysis.java:25:13:25:13 | x | SSA init(x) | 0 | 0 | | ModulusAnalysis.java:25:13:25:13 | x | SSA param(x) | 0 | 0 |
| ModulusAnalysis.java:25:17:25:18 | c1 | 0 | 42 | 0 | | ModulusAnalysis.java:25:17:25:18 | c1 | 0 | 42 | 0 |
| ModulusAnalysis.java:25:17:25:18 | c1 | SSA init(this.c1) | 0 | 0 | | ModulusAnalysis.java:25:17:25:18 | c1 | SSA entry def(this.c1) | 0 | 0 |
| ModulusAnalysis.java:25:23:25:23 | 3 | 0 | 3 | 0 | | ModulusAnalysis.java:25:23:25:23 | 3 | 0 | 3 | 0 |
| ModulusAnalysis.java:25:28:25:28 | y | SSA init(y) | 0 | 0 | | ModulusAnalysis.java:25:28:25:28 | y | SSA param(y) | 0 | 0 |
| ModulusAnalysis.java:25:32:25:33 | c1 | 0 | 42 | 0 | | ModulusAnalysis.java:25:32:25:33 | c1 | 0 | 42 | 0 |
| ModulusAnalysis.java:25:32:25:33 | c1 | SSA init(this.c1) | 0 | 0 | | ModulusAnalysis.java:25:32:25:33 | c1 | SSA entry def(this.c1) | 0 | 0 |
| ModulusAnalysis.java:25:38:25:38 | 7 | 0 | 7 | 0 | | ModulusAnalysis.java:25:38:25:38 | 7 | 0 | 7 | 0 |
| ModulusAnalysis.java:26:32:26:32 | x | 0 | 3 | 42 | | ModulusAnalysis.java:26:32:26:32 | x | 0 | 3 | 42 |
| ModulusAnalysis.java:26:32:26:32 | x | SSA init(x) | 0 | 0 | | ModulusAnalysis.java:26:32:26:32 | x | SSA param(x) | 0 | 0 |
| ModulusAnalysis.java:26:32:26:36 | ... - ... | 0 | 38 | 42 | | ModulusAnalysis.java:26:32:26:36 | ... - ... | 0 | 38 | 42 |
| ModulusAnalysis.java:26:32:26:36 | ... - ... | SSA init(x) | 35 | 42 | | ModulusAnalysis.java:26:32:26:36 | ... - ... | SSA param(x) | 35 | 42 |
| ModulusAnalysis.java:26:36:26:36 | y | 0 | 7 | 42 | | ModulusAnalysis.java:26:36:26:36 | y | 0 | 7 | 42 |
| ModulusAnalysis.java:26:36:26:36 | y | SSA init(y) | 0 | 0 | | ModulusAnalysis.java:26:36:26:36 | y | SSA param(y) | 0 | 0 |
| ModulusAnalysis.java:29:13:29:35 | l | 0 | 1 | 4 | | ModulusAnalysis.java:29:13:29:35 | l | 0 | 1 | 4 |
| ModulusAnalysis.java:29:17:29:26 | arr.length | SSA impl upd[untracked](arr.length) | 0 | 0 | | ModulusAnalysis.java:29:17:29:26 | arr.length | arr.length | 0 | 0 |
| ModulusAnalysis.java:29:17:29:30 | ... * ... | 0 | 0 | 4 | | ModulusAnalysis.java:29:17:29:30 | ... * ... | 0 | 0 | 4 |
| ModulusAnalysis.java:29:17:29:35 | ... - ... | 0 | 1 | 4 | | ModulusAnalysis.java:29:17:29:35 | ... - ... | 0 | 1 | 4 |
| ModulusAnalysis.java:29:30:29:30 | 4 | 0 | 4 | 0 | | ModulusAnalysis.java:29:30:29:30 | 4 | 0 | 4 | 0 |
@@ -87,13 +86,13 @@
| ModulusAnalysis.java:33:28:33:28 | l | 0 | 1 | 4 | | ModulusAnalysis.java:33:28:33:28 | l | 0 | 1 | 4 |
| ModulusAnalysis.java:33:28:33:28 | l | SSA def(l) | 0 | 0 | | ModulusAnalysis.java:33:28:33:28 | l | SSA def(l) | 0 | 0 |
| ModulusAnalysis.java:36:13:36:25 | ...=... | 0 | 3 | 4 | | ModulusAnalysis.java:36:13:36:25 | ...=... | 0 | 3 | 4 |
| ModulusAnalysis.java:36:17:36:17 | i | SSA init(i) | 0 | 0 | | ModulusAnalysis.java:36:17:36:17 | i | SSA param(i) | 0 | 0 |
| ModulusAnalysis.java:36:17:36:21 | ... * ... | 0 | 0 | 4 | | ModulusAnalysis.java:36:17:36:21 | ... * ... | 0 | 0 | 4 |
| ModulusAnalysis.java:36:17:36:25 | ... + ... | 0 | 3 | 4 | | ModulusAnalysis.java:36:17:36:25 | ... + ... | 0 | 3 | 4 |
| ModulusAnalysis.java:36:21:36:21 | 4 | 0 | 4 | 0 | | ModulusAnalysis.java:36:21:36:21 | 4 | 0 | 4 | 0 |
| ModulusAnalysis.java:36:25:36:25 | 3 | 0 | 3 | 0 | | ModulusAnalysis.java:36:25:36:25 | 3 | 0 | 3 | 0 |
| ModulusAnalysis.java:39:13:39:25 | ...=... | 0 | 7 | 8 | | ModulusAnalysis.java:39:13:39:25 | ...=... | 0 | 7 | 8 |
| ModulusAnalysis.java:39:17:39:17 | i | SSA init(i) | 0 | 0 | | ModulusAnalysis.java:39:17:39:17 | i | SSA param(i) | 0 | 0 |
| ModulusAnalysis.java:39:17:39:21 | ... * ... | 0 | 0 | 8 | | ModulusAnalysis.java:39:17:39:21 | ... * ... | 0 | 0 | 8 |
| ModulusAnalysis.java:39:17:39:25 | ... + ... | 0 | 7 | 8 | | ModulusAnalysis.java:39:17:39:25 | ... + ... | 0 | 7 | 8 |
| ModulusAnalysis.java:39:21:39:21 | 8 | 0 | 8 | 0 | | ModulusAnalysis.java:39:21:39:21 | 8 | 0 | 8 | 0 |
@@ -104,22 +103,22 @@
| ModulusAnalysis.java:44:32:44:32 | j | SSA phi(j) | 0 | 0 | | ModulusAnalysis.java:44:32:44:32 | j | SSA phi(j) | 0 | 0 |
| ModulusAnalysis.java:46:32:46:32 | j | 0 | 3 | 4 | | ModulusAnalysis.java:46:32:46:32 | j | 0 | 3 | 4 |
| ModulusAnalysis.java:46:32:46:32 | j | SSA phi(j) | 0 | 0 | | ModulusAnalysis.java:46:32:46:32 | j | SSA phi(j) | 0 | 0 |
| ModulusAnalysis.java:49:14:49:14 | x | SSA init(x) | 0 | 0 | | ModulusAnalysis.java:49:14:49:14 | x | SSA param(x) | 0 | 0 |
| ModulusAnalysis.java:49:18:49:19 | 15 | 0 | 15 | 0 | | ModulusAnalysis.java:49:18:49:19 | 15 | 0 | 15 | 0 |
| ModulusAnalysis.java:49:25:49:25 | 3 | 0 | 3 | 0 | | ModulusAnalysis.java:49:25:49:25 | 3 | 0 | 3 | 0 |
| ModulusAnalysis.java:50:32:50:32 | x | 0 | 3 | 16 | | ModulusAnalysis.java:50:32:50:32 | x | 0 | 3 | 16 |
| ModulusAnalysis.java:50:32:50:32 | x | SSA init(x) | 0 | 0 | | ModulusAnalysis.java:50:32:50:32 | x | SSA param(x) | 0 | 0 |
| ModulusAnalysis.java:56:18:56:22 | i | 0 | 0 | 0 | | ModulusAnalysis.java:56:18:56:22 | i | 0 | 0 | 0 |
| ModulusAnalysis.java:56:22:56:22 | 0 | 0 | 0 | 0 | | ModulusAnalysis.java:56:22:56:22 | 0 | 0 | 0 | 0 |
| ModulusAnalysis.java:56:25:56:25 | i | SSA phi(i) | 0 | 0 | | ModulusAnalysis.java:56:25:56:25 | i | SSA phi(i) | 0 | 0 |
| ModulusAnalysis.java:56:29:56:31 | cap | SSA init(cap) | 0 | 0 | | ModulusAnalysis.java:56:29:56:31 | cap | SSA param(cap) | 0 | 0 |
| ModulusAnalysis.java:56:34:56:34 | i | SSA phi(i) | 0 | 0 | | ModulusAnalysis.java:56:34:56:34 | i | SSA phi(i) | 0 | 0 |
| ModulusAnalysis.java:56:34:56:36 | ...++ | SSA phi(i) | 0 | 0 | | ModulusAnalysis.java:56:34:56:36 | ...++ | SSA phi(i) | 0 | 0 |
| ModulusAnalysis.java:57:32:57:32 | i | SSA phi(i) | 0 | 0 | | ModulusAnalysis.java:57:32:57:32 | i | SSA phi(i) | 0 | 0 |
| ModulusAnalysis.java:59:18:59:22 | j | 0 | 0 | 0 | | ModulusAnalysis.java:59:18:59:22 | j | 0 | 0 | 0 |
| ModulusAnalysis.java:59:22:59:22 | 0 | 0 | 0 | 0 | | ModulusAnalysis.java:59:22:59:22 | 0 | 0 | 0 | 0 |
| ModulusAnalysis.java:59:25:59:25 | j | SSA phi(j) | 0 | 0 | | ModulusAnalysis.java:59:25:59:25 | j | SSA phi(j) | 0 | 0 |
| ModulusAnalysis.java:59:29:59:31 | cap | SSA init(cap) | 0 | 0 | | ModulusAnalysis.java:59:29:59:31 | cap | SSA param(cap) | 0 | 0 |
| ModulusAnalysis.java:59:34:59:34 | j | SSA phi(j) | 0 | 0 | | ModulusAnalysis.java:59:34:59:34 | j | SSA phi(j) | 0 | 0 |
| ModulusAnalysis.java:59:34:59:39 | ...+=... | SSA phi(j) | 1 | 0 | | ModulusAnalysis.java:59:34:59:39 | ...+=... | SSA phi(j) | 1 | 0 |
| ModulusAnalysis.java:59:39:59:39 | 1 | 0 | 1 | 0 | | ModulusAnalysis.java:59:39:59:39 | 1 | 0 | 1 | 0 |
@@ -129,7 +128,7 @@
| ModulusAnalysis.java:62:25:62:25 | k | 0 | 0 | 3 | | ModulusAnalysis.java:62:25:62:25 | k | 0 | 0 | 3 |
| ModulusAnalysis.java:62:25:62:25 | k | SSA def(k) | 0 | 3 | | ModulusAnalysis.java:62:25:62:25 | k | SSA def(k) | 0 | 3 |
| ModulusAnalysis.java:62:25:62:25 | k | SSA phi(k) | 0 | 0 | | ModulusAnalysis.java:62:25:62:25 | k | SSA phi(k) | 0 | 0 |
| ModulusAnalysis.java:62:29:62:31 | cap | SSA init(cap) | 0 | 0 | | ModulusAnalysis.java:62:29:62:31 | cap | SSA param(cap) | 0 | 0 |
| ModulusAnalysis.java:62:34:62:34 | k | 0 | 0 | 3 | | ModulusAnalysis.java:62:34:62:34 | k | 0 | 0 | 3 |
| ModulusAnalysis.java:62:34:62:34 | k | SSA def(k) | 0 | 3 | | ModulusAnalysis.java:62:34:62:34 | k | SSA def(k) | 0 | 3 |
| ModulusAnalysis.java:62:34:62:34 | k | SSA phi(k) | 0 | 0 | | ModulusAnalysis.java:62:34:62:34 | k | SSA phi(k) | 0 | 0 |

View File

@@ -1,232 +1,232 @@
| A.java:3:9:3:9 | x | SSA init(x) | 0 | lower | NoReason | | A.java:3:9:3:9 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:3:9:3:9 | x | SSA init(x) | 0 | upper | NoReason | | A.java:3:9:3:9 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:3:13:3:15 | 500 | 0 | 500 | lower | NoReason | | A.java:3:13:3:15 | 500 | 0 | 500 | lower | NoReason |
| A.java:3:13:3:15 | 500 | 0 | 500 | upper | NoReason | | A.java:3:13:3:15 | 500 | 0 | 500 | upper | NoReason |
| A.java:4:11:4:11 | x | 0 | 499 | upper | ... < ... | | A.java:4:11:4:11 | x | 0 | 499 | upper | ... < ... |
| A.java:4:11:4:11 | x | SSA init(x) | 0 | lower | NoReason | | A.java:4:11:4:11 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:4:11:4:11 | x | SSA init(x) | 0 | upper | NoReason | | A.java:4:11:4:11 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:4:15:4:17 | 400 | 0 | 400 | lower | NoReason | | A.java:4:15:4:17 | 400 | 0 | 400 | lower | NoReason |
| A.java:4:15:4:17 | 400 | 0 | 400 | upper | NoReason | | A.java:4:15:4:17 | 400 | 0 | 400 | upper | NoReason |
| A.java:5:16:5:16 | x | 0 | 401 | lower | ... > ... | | A.java:5:16:5:16 | x | 0 | 401 | lower | ... > ... |
| A.java:5:16:5:16 | x | 0 | 499 | upper | ... < ... | | A.java:5:16:5:16 | x | 0 | 499 | upper | ... < ... |
| A.java:5:16:5:16 | x | SSA init(x) | 0 | lower | NoReason | | A.java:5:16:5:16 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:5:16:5:16 | x | SSA init(x) | 0 | upper | NoReason | | A.java:5:16:5:16 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:8:11:8:11 | y | SSA init(y) | 0 | lower | NoReason | | A.java:8:11:8:11 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:8:11:8:11 | y | SSA init(y) | 0 | upper | NoReason | | A.java:8:11:8:11 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:8:11:8:15 | ... - ... | SSA init(y) | -2 | lower | NoReason | | A.java:8:11:8:15 | ... - ... | SSA param(y) | -2 | lower | NoReason |
| A.java:8:11:8:15 | ... - ... | SSA init(y) | -2 | upper | NoReason | | A.java:8:11:8:15 | ... - ... | SSA param(y) | -2 | upper | NoReason |
| A.java:8:15:8:15 | 2 | 0 | 2 | lower | NoReason | | A.java:8:15:8:15 | 2 | 0 | 2 | lower | NoReason |
| A.java:8:15:8:15 | 2 | 0 | 2 | upper | NoReason | | A.java:8:15:8:15 | 2 | 0 | 2 | upper | NoReason |
| A.java:8:20:8:20 | x | 0 | 400 | upper | ... > ... | | A.java:8:20:8:20 | x | 0 | 400 | upper | ... > ... |
| A.java:8:20:8:20 | x | SSA init(x) | 0 | lower | NoReason | | A.java:8:20:8:20 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:8:20:8:20 | x | SSA init(x) | 0 | upper | NoReason | | A.java:8:20:8:20 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:8:25:8:25 | y | 0 | 402 | upper | ... == ... | | A.java:8:25:8:25 | y | 0 | 402 | upper | ... == ... |
| A.java:8:25:8:25 | y | SSA init(x) | 2 | lower | ... == ... | | A.java:8:25:8:25 | y | SSA param(x) | 2 | lower | ... == ... |
| A.java:8:25:8:25 | y | SSA init(x) | 2 | upper | ... == ... | | A.java:8:25:8:25 | y | SSA param(x) | 2 | upper | ... == ... |
| A.java:8:25:8:25 | y | SSA init(y) | 0 | lower | NoReason | | A.java:8:25:8:25 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:8:25:8:25 | y | SSA init(y) | 0 | upper | NoReason | | A.java:8:25:8:25 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:8:29:8:31 | 300 | 0 | 300 | lower | NoReason | | A.java:8:29:8:31 | 300 | 0 | 300 | lower | NoReason |
| A.java:8:29:8:31 | 300 | 0 | 300 | upper | NoReason | | A.java:8:29:8:31 | 300 | 0 | 300 | upper | NoReason |
| A.java:9:16:9:16 | x | 0 | 299 | lower | ... > ... | | A.java:9:16:9:16 | x | 0 | 299 | lower | ... > ... |
| A.java:9:16:9:16 | x | 0 | 400 | upper | ... > ... | | A.java:9:16:9:16 | x | 0 | 400 | upper | ... > ... |
| A.java:9:16:9:16 | x | SSA init(x) | 0 | lower | NoReason | | A.java:9:16:9:16 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:9:16:9:16 | x | SSA init(x) | 0 | upper | NoReason | | A.java:9:16:9:16 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:9:16:9:16 | x | SSA init(y) | -2 | lower | ... == ... | | A.java:9:16:9:16 | x | SSA param(y) | -2 | lower | ... == ... |
| A.java:9:16:9:16 | x | SSA init(y) | -2 | upper | ... == ... | | A.java:9:16:9:16 | x | SSA param(y) | -2 | upper | ... == ... |
| A.java:9:16:9:20 | ... + ... | 0 | 600 | lower | ... > ... | | A.java:9:16:9:20 | ... + ... | 0 | 600 | lower | ... > ... |
| A.java:9:16:9:20 | ... + ... | 0 | 802 | upper | ... == ... | | A.java:9:16:9:20 | ... + ... | 0 | 802 | upper | ... == ... |
| A.java:9:16:9:20 | ... + ... | 0 | 802 | upper | ... > ... | | A.java:9:16:9:20 | ... + ... | 0 | 802 | upper | ... > ... |
| A.java:9:16:9:20 | ... + ... | SSA init(x) | 301 | lower | ... == ... | | A.java:9:16:9:20 | ... + ... | SSA param(x) | 301 | lower | ... == ... |
| A.java:9:16:9:20 | ... + ... | SSA init(x) | 301 | lower | NoReason | | A.java:9:16:9:20 | ... + ... | SSA param(x) | 301 | lower | NoReason |
| A.java:9:16:9:20 | ... + ... | SSA init(x) | 402 | upper | ... == ... | | A.java:9:16:9:20 | ... + ... | SSA param(x) | 402 | upper | ... == ... |
| A.java:9:16:9:20 | ... + ... | SSA init(x) | 402 | upper | NoReason | | A.java:9:16:9:20 | ... + ... | SSA param(x) | 402 | upper | NoReason |
| A.java:9:16:9:20 | ... + ... | SSA init(y) | 299 | lower | ... == ... | | A.java:9:16:9:20 | ... + ... | SSA param(y) | 299 | lower | ... == ... |
| A.java:9:16:9:20 | ... + ... | SSA init(y) | 299 | lower | NoReason | | A.java:9:16:9:20 | ... + ... | SSA param(y) | 299 | lower | NoReason |
| A.java:9:16:9:20 | ... + ... | SSA init(y) | 400 | upper | ... == ... | | A.java:9:16:9:20 | ... + ... | SSA param(y) | 400 | upper | ... == ... |
| A.java:9:16:9:20 | ... + ... | SSA init(y) | 400 | upper | NoReason | | A.java:9:16:9:20 | ... + ... | SSA param(y) | 400 | upper | NoReason |
| A.java:9:20:9:20 | y | 0 | 301 | lower | ... > ... | | A.java:9:20:9:20 | y | 0 | 301 | lower | ... > ... |
| A.java:9:20:9:20 | y | 0 | 402 | upper | ... == ... | | A.java:9:20:9:20 | y | 0 | 402 | upper | ... == ... |
| A.java:9:20:9:20 | y | SSA init(x) | 2 | lower | ... == ... | | A.java:9:20:9:20 | y | SSA param(x) | 2 | lower | ... == ... |
| A.java:9:20:9:20 | y | SSA init(x) | 2 | upper | ... == ... | | A.java:9:20:9:20 | y | SSA param(x) | 2 | upper | ... == ... |
| A.java:9:20:9:20 | y | SSA init(y) | 0 | lower | NoReason | | A.java:9:20:9:20 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:9:20:9:20 | y | SSA init(y) | 0 | upper | NoReason | | A.java:9:20:9:20 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:12:11:12:11 | x | 0 | 400 | upper | ... > ... | | A.java:12:11:12:11 | x | 0 | 400 | upper | ... > ... |
| A.java:12:11:12:11 | x | SSA init(x) | 0 | lower | NoReason | | A.java:12:11:12:11 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:12:11:12:11 | x | SSA init(x) | 0 | upper | NoReason | | A.java:12:11:12:11 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:12:16:12:16 | y | SSA init(y) | 0 | lower | NoReason | | A.java:12:16:12:16 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:12:16:12:16 | y | SSA init(y) | 0 | upper | NoReason | | A.java:12:16:12:16 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:12:16:12:20 | ... + ... | SSA init(y) | 1 | lower | NoReason | | A.java:12:16:12:20 | ... + ... | SSA param(y) | 1 | lower | NoReason |
| A.java:12:16:12:20 | ... + ... | SSA init(y) | 1 | upper | NoReason | | A.java:12:16:12:20 | ... + ... | SSA param(y) | 1 | upper | NoReason |
| A.java:12:20:12:20 | 1 | 0 | 1 | lower | NoReason | | A.java:12:20:12:20 | 1 | 0 | 1 | lower | NoReason |
| A.java:12:20:12:20 | 1 | 0 | 1 | upper | NoReason | | A.java:12:20:12:20 | 1 | 0 | 1 | upper | NoReason |
| A.java:13:13:13:23 | sum | SSA init(y) | 400 | upper | NoReason | | A.java:13:13:13:23 | sum | SSA param(y) | 400 | upper | NoReason |
| A.java:13:19:13:19 | x | 0 | 400 | upper | ... > ... | | A.java:13:19:13:19 | x | 0 | 400 | upper | ... > ... |
| A.java:13:19:13:19 | x | SSA init(x) | 0 | lower | NoReason | | A.java:13:19:13:19 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:13:19:13:19 | x | SSA init(x) | 0 | upper | NoReason | | A.java:13:19:13:19 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:13:19:13:23 | ... + ... | SSA init(y) | 400 | upper | NoReason | | A.java:13:19:13:23 | ... + ... | SSA param(y) | 400 | upper | NoReason |
| A.java:13:23:13:23 | y | SSA init(y) | 0 | lower | NoReason | | A.java:13:23:13:23 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:13:23:13:23 | y | SSA init(y) | 0 | upper | NoReason | | A.java:13:23:13:23 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:15:13:15:13 | y | 0 | 399 | upper | ... != ... | | A.java:15:13:15:13 | y | 0 | 399 | upper | ... != ... |
| A.java:15:13:15:13 | y | SSA init(x) | -1 | lower | ... != ... | | A.java:15:13:15:13 | y | SSA param(x) | -1 | lower | ... != ... |
| A.java:15:13:15:13 | y | SSA init(x) | -1 | upper | ... != ... | | A.java:15:13:15:13 | y | SSA param(x) | -1 | upper | ... != ... |
| A.java:15:13:15:13 | y | SSA init(y) | 0 | lower | NoReason | | A.java:15:13:15:13 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:15:13:15:13 | y | SSA init(y) | 0 | upper | NoReason | | A.java:15:13:15:13 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:15:17:15:19 | 300 | 0 | 300 | lower | NoReason | | A.java:15:17:15:19 | 300 | 0 | 300 | lower | NoReason |
| A.java:15:17:15:19 | 300 | 0 | 300 | upper | NoReason | | A.java:15:17:15:19 | 300 | 0 | 300 | upper | NoReason |
| A.java:16:15:16:25 | sum | 0 | 603 | lower | ... > ... | | A.java:16:15:16:25 | sum | 0 | 603 | lower | ... > ... |
| A.java:16:15:16:25 | sum | 0 | 799 | upper | ... != ... | | A.java:16:15:16:25 | sum | 0 | 799 | upper | ... != ... |
| A.java:16:15:16:25 | sum | 0 | 799 | upper | ... > ... | | A.java:16:15:16:25 | sum | 0 | 799 | upper | ... > ... |
| A.java:16:15:16:25 | sum | SSA init(x) | 301 | lower | ... != ... | | A.java:16:15:16:25 | sum | SSA param(x) | 301 | lower | ... != ... |
| A.java:16:15:16:25 | sum | SSA init(x) | 301 | lower | NoReason | | A.java:16:15:16:25 | sum | SSA param(x) | 301 | lower | NoReason |
| A.java:16:15:16:25 | sum | SSA init(x) | 399 | upper | ... != ... | | A.java:16:15:16:25 | sum | SSA param(x) | 399 | upper | ... != ... |
| A.java:16:15:16:25 | sum | SSA init(x) | 399 | upper | NoReason | | A.java:16:15:16:25 | sum | SSA param(x) | 399 | upper | NoReason |
| A.java:16:15:16:25 | sum | SSA init(y) | 302 | lower | ... != ... | | A.java:16:15:16:25 | sum | SSA param(y) | 302 | lower | ... != ... |
| A.java:16:15:16:25 | sum | SSA init(y) | 302 | lower | NoReason | | A.java:16:15:16:25 | sum | SSA param(y) | 302 | lower | NoReason |
| A.java:16:15:16:25 | sum | SSA init(y) | 400 | upper | ... != ... | | A.java:16:15:16:25 | sum | SSA param(y) | 400 | upper | ... != ... |
| A.java:16:15:16:25 | sum | SSA init(y) | 400 | upper | NoReason | | A.java:16:15:16:25 | sum | SSA param(y) | 400 | upper | NoReason |
| A.java:16:21:16:21 | x | 0 | 302 | lower | ... > ... | | A.java:16:21:16:21 | x | 0 | 302 | lower | ... > ... |
| A.java:16:21:16:21 | x | 0 | 400 | upper | ... > ... | | A.java:16:21:16:21 | x | 0 | 400 | upper | ... > ... |
| A.java:16:21:16:21 | x | SSA init(x) | 0 | lower | NoReason | | A.java:16:21:16:21 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:16:21:16:21 | x | SSA init(x) | 0 | upper | NoReason | | A.java:16:21:16:21 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:16:21:16:21 | x | SSA init(y) | 1 | lower | ... != ... | | A.java:16:21:16:21 | x | SSA param(y) | 1 | lower | ... != ... |
| A.java:16:21:16:21 | x | SSA init(y) | 1 | upper | ... != ... | | A.java:16:21:16:21 | x | SSA param(y) | 1 | upper | ... != ... |
| A.java:16:21:16:25 | ... + ... | 0 | 603 | lower | ... > ... | | A.java:16:21:16:25 | ... + ... | 0 | 603 | lower | ... > ... |
| A.java:16:21:16:25 | ... + ... | 0 | 799 | upper | ... != ... | | A.java:16:21:16:25 | ... + ... | 0 | 799 | upper | ... != ... |
| A.java:16:21:16:25 | ... + ... | 0 | 799 | upper | ... > ... | | A.java:16:21:16:25 | ... + ... | 0 | 799 | upper | ... > ... |
| A.java:16:21:16:25 | ... + ... | SSA init(x) | 301 | lower | ... != ... | | A.java:16:21:16:25 | ... + ... | SSA param(x) | 301 | lower | ... != ... |
| A.java:16:21:16:25 | ... + ... | SSA init(x) | 301 | lower | NoReason | | A.java:16:21:16:25 | ... + ... | SSA param(x) | 301 | lower | NoReason |
| A.java:16:21:16:25 | ... + ... | SSA init(x) | 399 | upper | ... != ... | | A.java:16:21:16:25 | ... + ... | SSA param(x) | 399 | upper | ... != ... |
| A.java:16:21:16:25 | ... + ... | SSA init(x) | 399 | upper | NoReason | | A.java:16:21:16:25 | ... + ... | SSA param(x) | 399 | upper | NoReason |
| A.java:16:21:16:25 | ... + ... | SSA init(y) | 302 | lower | ... != ... | | A.java:16:21:16:25 | ... + ... | SSA param(y) | 302 | lower | ... != ... |
| A.java:16:21:16:25 | ... + ... | SSA init(y) | 302 | lower | NoReason | | A.java:16:21:16:25 | ... + ... | SSA param(y) | 302 | lower | NoReason |
| A.java:16:21:16:25 | ... + ... | SSA init(y) | 400 | upper | ... != ... | | A.java:16:21:16:25 | ... + ... | SSA param(y) | 400 | upper | ... != ... |
| A.java:16:21:16:25 | ... + ... | SSA init(y) | 400 | upper | NoReason | | A.java:16:21:16:25 | ... + ... | SSA param(y) | 400 | upper | NoReason |
| A.java:16:25:16:25 | y | 0 | 301 | lower | ... > ... | | A.java:16:25:16:25 | y | 0 | 301 | lower | ... > ... |
| A.java:16:25:16:25 | y | 0 | 399 | upper | ... != ... | | A.java:16:25:16:25 | y | 0 | 399 | upper | ... != ... |
| A.java:16:25:16:25 | y | SSA init(x) | -1 | lower | ... != ... | | A.java:16:25:16:25 | y | SSA param(x) | -1 | lower | ... != ... |
| A.java:16:25:16:25 | y | SSA init(x) | -1 | upper | ... != ... | | A.java:16:25:16:25 | y | SSA param(x) | -1 | upper | ... != ... |
| A.java:16:25:16:25 | y | SSA init(y) | 0 | lower | NoReason | | A.java:16:25:16:25 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:16:25:16:25 | y | SSA init(y) | 0 | upper | NoReason | | A.java:16:25:16:25 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:20:11:20:11 | x | 0 | 400 | upper | ... > ... | | A.java:20:11:20:11 | x | 0 | 400 | upper | ... > ... |
| A.java:20:11:20:11 | x | SSA init(x) | 0 | lower | NoReason | | A.java:20:11:20:11 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:20:11:20:11 | x | SSA init(x) | 0 | upper | NoReason | | A.java:20:11:20:11 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:20:15:20:17 | 500 | 0 | 500 | lower | NoReason | | A.java:20:15:20:17 | 500 | 0 | 500 | lower | NoReason |
| A.java:20:15:20:17 | 500 | 0 | 500 | upper | NoReason | | A.java:20:15:20:17 | 500 | 0 | 500 | upper | NoReason |
| A.java:21:16:21:16 | x | 0 | 400 | upper | ... > ... | | A.java:21:16:21:16 | x | 0 | 400 | upper | ... > ... |
| A.java:21:16:21:16 | x | 0 | 501 | lower | ... > ... | | A.java:21:16:21:16 | x | 0 | 501 | lower | ... > ... |
| A.java:21:16:21:16 | x | SSA init(x) | 0 | lower | NoReason | | A.java:21:16:21:16 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:21:16:21:16 | x | SSA init(x) | 0 | upper | NoReason | | A.java:21:16:21:16 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:25:12:25:12 | 0 | 0 | 0 | lower | NoReason | | A.java:25:12:25:12 | 0 | 0 | 0 | lower | NoReason |
| A.java:25:12:25:12 | 0 | 0 | 0 | upper | NoReason | | A.java:25:12:25:12 | 0 | 0 | 0 | upper | NoReason |
| A.java:29:9:29:9 | x | SSA init(x) | 0 | lower | NoReason | | A.java:29:9:29:9 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:29:9:29:9 | x | SSA init(x) | 0 | upper | NoReason | | A.java:29:9:29:9 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:29:13:29:15 | 500 | 0 | 500 | lower | NoReason | | A.java:29:13:29:15 | 500 | 0 | 500 | lower | NoReason |
| A.java:29:13:29:15 | 500 | 0 | 500 | upper | NoReason | | A.java:29:13:29:15 | 500 | 0 | 500 | upper | NoReason |
| A.java:30:11:30:11 | x | 0 | 499 | upper | ... < ... | | A.java:30:11:30:11 | x | 0 | 499 | upper | ... < ... |
| A.java:30:11:30:11 | x | SSA init(x) | 0 | lower | NoReason | | A.java:30:11:30:11 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:30:11:30:11 | x | SSA init(x) | 0 | upper | NoReason | | A.java:30:11:30:11 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:30:15:30:17 | 400 | 0 | 400 | lower | NoReason | | A.java:30:15:30:17 | 400 | 0 | 400 | lower | NoReason |
| A.java:30:15:30:17 | 400 | 0 | 400 | upper | NoReason | | A.java:30:15:30:17 | 400 | 0 | 400 | upper | NoReason |
| A.java:31:16:31:16 | x | 0 | 401 | lower | ... > ... | | A.java:31:16:31:16 | x | 0 | 401 | lower | ... > ... |
| A.java:31:16:31:16 | x | 0 | 499 | upper | ... < ... | | A.java:31:16:31:16 | x | 0 | 499 | upper | ... < ... |
| A.java:31:16:31:16 | x | SSA init(x) | 0 | lower | NoReason | | A.java:31:16:31:16 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:31:16:31:16 | x | SSA init(x) | 0 | upper | NoReason | | A.java:31:16:31:16 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:34:11:34:11 | y | SSA init(y) | 0 | lower | NoReason | | A.java:34:11:34:11 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:34:11:34:11 | y | SSA init(y) | 0 | upper | NoReason | | A.java:34:11:34:11 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:34:16:34:16 | x | 0 | 400 | upper | ... > ... | | A.java:34:16:34:16 | x | 0 | 400 | upper | ... > ... |
| A.java:34:16:34:16 | x | SSA init(x) | 0 | lower | NoReason | | A.java:34:16:34:16 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:34:16:34:16 | x | SSA init(x) | 0 | upper | NoReason | | A.java:34:16:34:16 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:34:16:34:20 | ... - ... | 0 | 399 | upper | ... > ... | | A.java:34:16:34:20 | ... - ... | 0 | 399 | upper | ... > ... |
| A.java:34:16:34:20 | ... - ... | SSA init(x) | -1 | lower | NoReason | | A.java:34:16:34:20 | ... - ... | SSA param(x) | -1 | lower | NoReason |
| A.java:34:16:34:20 | ... - ... | SSA init(x) | -1 | upper | NoReason | | A.java:34:16:34:20 | ... - ... | SSA param(x) | -1 | upper | NoReason |
| A.java:34:20:34:20 | 1 | 0 | 1 | lower | NoReason | | A.java:34:20:34:20 | 1 | 0 | 1 | lower | NoReason |
| A.java:34:20:34:20 | 1 | 0 | 1 | upper | NoReason | | A.java:34:20:34:20 | 1 | 0 | 1 | upper | NoReason |
| A.java:34:25:34:25 | y | 0 | 399 | upper | ... == ... | | A.java:34:25:34:25 | y | 0 | 399 | upper | ... == ... |
| A.java:34:25:34:25 | y | SSA init(x) | -1 | lower | ... == ... | | A.java:34:25:34:25 | y | SSA param(x) | -1 | lower | ... == ... |
| A.java:34:25:34:25 | y | SSA init(x) | -1 | upper | ... == ... | | A.java:34:25:34:25 | y | SSA param(x) | -1 | upper | ... == ... |
| A.java:34:25:34:25 | y | SSA init(y) | 0 | lower | NoReason | | A.java:34:25:34:25 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:34:25:34:25 | y | SSA init(y) | 0 | upper | NoReason | | A.java:34:25:34:25 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:34:29:34:31 | 300 | 0 | 300 | lower | NoReason | | A.java:34:29:34:31 | 300 | 0 | 300 | lower | NoReason |
| A.java:34:29:34:31 | 300 | 0 | 300 | upper | NoReason | | A.java:34:29:34:31 | 300 | 0 | 300 | upper | NoReason |
| A.java:34:36:34:36 | y | 0 | 301 | lower | ... > ... | | A.java:34:36:34:36 | y | 0 | 301 | lower | ... > ... |
| A.java:34:36:34:36 | y | 0 | 399 | upper | ... == ... | | A.java:34:36:34:36 | y | 0 | 399 | upper | ... == ... |
| A.java:34:36:34:36 | y | SSA init(x) | -1 | lower | ... == ... | | A.java:34:36:34:36 | y | SSA param(x) | -1 | lower | ... == ... |
| A.java:34:36:34:36 | y | SSA init(x) | -1 | upper | ... == ... | | A.java:34:36:34:36 | y | SSA param(x) | -1 | upper | ... == ... |
| A.java:34:36:34:36 | y | SSA init(y) | 0 | lower | NoReason | | A.java:34:36:34:36 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:34:36:34:36 | y | SSA init(y) | 0 | upper | NoReason | | A.java:34:36:34:36 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:34:36:34:40 | ... + ... | 0 | 303 | lower | ... > ... | | A.java:34:36:34:40 | ... + ... | 0 | 303 | lower | ... > ... |
| A.java:34:36:34:40 | ... + ... | 0 | 401 | upper | ... == ... | | A.java:34:36:34:40 | ... + ... | 0 | 401 | upper | ... == ... |
| A.java:34:36:34:40 | ... + ... | SSA init(x) | 1 | lower | ... == ... | | A.java:34:36:34:40 | ... + ... | SSA param(x) | 1 | lower | ... == ... |
| A.java:34:36:34:40 | ... + ... | SSA init(x) | 1 | upper | ... == ... | | A.java:34:36:34:40 | ... + ... | SSA param(x) | 1 | upper | ... == ... |
| A.java:34:36:34:40 | ... + ... | SSA init(y) | 2 | lower | NoReason | | A.java:34:36:34:40 | ... + ... | SSA param(y) | 2 | lower | NoReason |
| A.java:34:36:34:40 | ... + ... | SSA init(y) | 2 | upper | NoReason | | A.java:34:36:34:40 | ... + ... | SSA param(y) | 2 | upper | NoReason |
| A.java:34:40:34:40 | 2 | 0 | 2 | lower | NoReason | | A.java:34:40:34:40 | 2 | 0 | 2 | lower | NoReason |
| A.java:34:40:34:40 | 2 | 0 | 2 | upper | NoReason | | A.java:34:40:34:40 | 2 | 0 | 2 | upper | NoReason |
| A.java:34:45:34:45 | z | SSA init(z) | 0 | lower | NoReason | | A.java:34:45:34:45 | z | SSA param(z) | 0 | lower | NoReason |
| A.java:34:45:34:45 | z | SSA init(z) | 0 | upper | NoReason | | A.java:34:45:34:45 | z | SSA param(z) | 0 | upper | NoReason |
| A.java:34:50:34:50 | z | 0 | 303 | lower | ... == ... | | A.java:34:50:34:50 | z | 0 | 303 | lower | ... == ... |
| A.java:34:50:34:50 | z | 0 | 401 | upper | ... == ... | | A.java:34:50:34:50 | z | 0 | 401 | upper | ... == ... |
| A.java:34:50:34:50 | z | SSA init(x) | 1 | lower | ... == ... | | A.java:34:50:34:50 | z | SSA param(x) | 1 | lower | ... == ... |
| A.java:34:50:34:50 | z | SSA init(x) | 1 | upper | ... == ... | | A.java:34:50:34:50 | z | SSA param(x) | 1 | upper | ... == ... |
| A.java:34:50:34:50 | z | SSA init(y) | 2 | lower | ... == ... | | A.java:34:50:34:50 | z | SSA param(y) | 2 | lower | ... == ... |
| A.java:34:50:34:50 | z | SSA init(y) | 2 | upper | ... == ... | | A.java:34:50:34:50 | z | SSA param(y) | 2 | upper | ... == ... |
| A.java:34:50:34:50 | z | SSA init(z) | 0 | lower | NoReason | | A.java:34:50:34:50 | z | SSA param(z) | 0 | lower | NoReason |
| A.java:34:50:34:50 | z | SSA init(z) | 0 | upper | NoReason | | A.java:34:50:34:50 | z | SSA param(z) | 0 | upper | NoReason |
| A.java:34:55:34:57 | 350 | 0 | 350 | lower | NoReason | | A.java:34:55:34:57 | 350 | 0 | 350 | lower | NoReason |
| A.java:34:55:34:57 | 350 | 0 | 350 | upper | NoReason | | A.java:34:55:34:57 | 350 | 0 | 350 | upper | NoReason |
| A.java:35:16:35:16 | x | 0 | 349 | lower | ... == ... | | A.java:35:16:35:16 | x | 0 | 349 | lower | ... == ... |
| A.java:35:16:35:16 | x | 0 | 349 | upper | ... == ... | | A.java:35:16:35:16 | x | 0 | 349 | upper | ... == ... |
| A.java:35:16:35:16 | x | SSA init(x) | 0 | lower | NoReason | | A.java:35:16:35:16 | x | SSA param(x) | 0 | lower | NoReason |
| A.java:35:16:35:16 | x | SSA init(x) | 0 | upper | NoReason | | A.java:35:16:35:16 | x | SSA param(x) | 0 | upper | NoReason |
| A.java:35:16:35:16 | x | SSA init(y) | 1 | lower | ... == ... | | A.java:35:16:35:16 | x | SSA param(y) | 1 | lower | ... == ... |
| A.java:35:16:35:16 | x | SSA init(y) | 1 | upper | ... == ... | | A.java:35:16:35:16 | x | SSA param(y) | 1 | upper | ... == ... |
| A.java:35:16:35:16 | x | SSA init(z) | -1 | lower | ... == ... | | A.java:35:16:35:16 | x | SSA param(z) | -1 | lower | ... == ... |
| A.java:35:16:35:16 | x | SSA init(z) | -1 | upper | ... == ... | | A.java:35:16:35:16 | x | SSA param(z) | -1 | upper | ... == ... |
| A.java:35:16:35:20 | ... + ... | 0 | 697 | lower | ... == ... | | A.java:35:16:35:20 | ... + ... | 0 | 697 | lower | ... == ... |
| A.java:35:16:35:20 | ... + ... | 0 | 697 | upper | ... == ... | | A.java:35:16:35:20 | ... + ... | 0 | 697 | upper | ... == ... |
| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | lower | ... == ... | | A.java:35:16:35:20 | ... + ... | SSA param(x) | 348 | lower | ... == ... |
| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | lower | NoReason | | A.java:35:16:35:20 | ... + ... | SSA param(x) | 348 | lower | NoReason |
| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | upper | ... == ... | | A.java:35:16:35:20 | ... + ... | SSA param(x) | 348 | upper | ... == ... |
| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | upper | NoReason | | A.java:35:16:35:20 | ... + ... | SSA param(x) | 348 | upper | NoReason |
| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | lower | ... == ... | | A.java:35:16:35:20 | ... + ... | SSA param(y) | 349 | lower | ... == ... |
| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | lower | NoReason | | A.java:35:16:35:20 | ... + ... | SSA param(y) | 349 | lower | NoReason |
| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | upper | ... == ... | | A.java:35:16:35:20 | ... + ... | SSA param(y) | 349 | upper | ... == ... |
| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | upper | NoReason | | A.java:35:16:35:20 | ... + ... | SSA param(y) | 349 | upper | NoReason |
| A.java:35:16:35:20 | ... + ... | SSA init(z) | 347 | lower | ... == ... | | A.java:35:16:35:20 | ... + ... | SSA param(z) | 347 | lower | ... == ... |
| A.java:35:16:35:20 | ... + ... | SSA init(z) | 347 | upper | ... == ... | | A.java:35:16:35:20 | ... + ... | SSA param(z) | 347 | upper | ... == ... |
| A.java:35:16:35:24 | ... + ... | 0 | 1047 | lower | ... == ... | | A.java:35:16:35:24 | ... + ... | 0 | 1047 | lower | ... == ... |
| A.java:35:16:35:24 | ... + ... | 0 | 1047 | upper | ... == ... | | A.java:35:16:35:24 | ... + ... | 0 | 1047 | upper | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | lower | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(x) | 698 | lower | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | lower | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(x) | 698 | lower | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | lower | NoReason | | A.java:35:16:35:24 | ... + ... | SSA param(x) | 698 | lower | NoReason |
| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | upper | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(x) | 698 | upper | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | upper | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(x) | 698 | upper | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | upper | NoReason | | A.java:35:16:35:24 | ... + ... | SSA param(x) | 698 | upper | NoReason |
| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | lower | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(y) | 699 | lower | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | lower | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(y) | 699 | lower | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | lower | NoReason | | A.java:35:16:35:24 | ... + ... | SSA param(y) | 699 | lower | NoReason |
| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | upper | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(y) | 699 | upper | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | upper | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(y) | 699 | upper | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | upper | NoReason | | A.java:35:16:35:24 | ... + ... | SSA param(y) | 699 | upper | NoReason |
| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | lower | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(z) | 697 | lower | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | lower | NoReason | | A.java:35:16:35:24 | ... + ... | SSA param(z) | 697 | lower | NoReason |
| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | upper | ... == ... | | A.java:35:16:35:24 | ... + ... | SSA param(z) | 697 | upper | ... == ... |
| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | upper | NoReason | | A.java:35:16:35:24 | ... + ... | SSA param(z) | 697 | upper | NoReason |
| A.java:35:20:35:20 | y | 0 | 348 | lower | ... == ... | | A.java:35:20:35:20 | y | 0 | 348 | lower | ... == ... |
| A.java:35:20:35:20 | y | 0 | 348 | upper | ... == ... | | A.java:35:20:35:20 | y | 0 | 348 | upper | ... == ... |
| A.java:35:20:35:20 | y | SSA init(x) | -1 | lower | ... == ... | | A.java:35:20:35:20 | y | SSA param(x) | -1 | lower | ... == ... |
| A.java:35:20:35:20 | y | SSA init(x) | -1 | upper | ... == ... | | A.java:35:20:35:20 | y | SSA param(x) | -1 | upper | ... == ... |
| A.java:35:20:35:20 | y | SSA init(y) | 0 | lower | NoReason | | A.java:35:20:35:20 | y | SSA param(y) | 0 | lower | NoReason |
| A.java:35:20:35:20 | y | SSA init(y) | 0 | upper | NoReason | | A.java:35:20:35:20 | y | SSA param(y) | 0 | upper | NoReason |
| A.java:35:20:35:20 | y | SSA init(z) | -2 | lower | ... == ... | | A.java:35:20:35:20 | y | SSA param(z) | -2 | lower | ... == ... |
| A.java:35:20:35:20 | y | SSA init(z) | -2 | upper | ... == ... | | A.java:35:20:35:20 | y | SSA param(z) | -2 | upper | ... == ... |
| A.java:35:24:35:24 | z | 0 | 350 | lower | ... == ... | | A.java:35:24:35:24 | z | 0 | 350 | lower | ... == ... |
| A.java:35:24:35:24 | z | 0 | 350 | upper | ... == ... | | A.java:35:24:35:24 | z | 0 | 350 | upper | ... == ... |
| A.java:35:24:35:24 | z | SSA init(x) | 1 | lower | ... == ... | | A.java:35:24:35:24 | z | SSA param(x) | 1 | lower | ... == ... |
| A.java:35:24:35:24 | z | SSA init(x) | 1 | upper | ... == ... | | A.java:35:24:35:24 | z | SSA param(x) | 1 | upper | ... == ... |
| A.java:35:24:35:24 | z | SSA init(y) | 2 | lower | ... == ... | | A.java:35:24:35:24 | z | SSA param(y) | 2 | lower | ... == ... |
| A.java:35:24:35:24 | z | SSA init(y) | 2 | upper | ... == ... | | A.java:35:24:35:24 | z | SSA param(y) | 2 | upper | ... == ... |
| A.java:35:24:35:24 | z | SSA init(z) | 0 | lower | NoReason | | A.java:35:24:35:24 | z | SSA param(z) | 0 | lower | NoReason |
| A.java:35:24:35:24 | z | SSA init(z) | 0 | upper | NoReason | | A.java:35:24:35:24 | z | SSA param(z) | 0 | upper | NoReason |
| A.java:39:12:39:12 | 0 | 0 | 0 | lower | NoReason | | A.java:39:12:39:12 | 0 | 0 | 0 | lower | NoReason |
| A.java:39:12:39:12 | 0 | 0 | 0 | upper | NoReason | | A.java:39:12:39:12 | 0 | 0 | 0 | upper | NoReason |

View File

@@ -3,6 +3,6 @@ import semmle.code.java.dataflow.SSA
from int uses, int live from int uses, int live
where where
uses = strictcount(SsaVariable ssa, VarRead use | use = ssa.getAUse()) and uses = strictcount(SsaDefinition ssa, VarRead use | use = ssa.getARead()) and
live = strictcount(SsaVariable ssa, BasicBlock b | ssa.isLiveAtEndOfBlock(b)) live = strictcount(SsaDefinition ssa, BasicBlock b | ssa.isLiveAtEndOfBlock(b))
select uses, live select uses, live

View File

@@ -1,9 +1,9 @@
| Nested.java:8:29:8:57 | SSA init(next(..).p1) | Nested.java:4:34:10:3 | SSA init(p1) | | Nested.java:8:29:8:57 | SSA capture def(next(..).p1) | Nested.java:4:34:10:3 | SSA param(p1) |
| Nested.java:8:29:8:57 | SSA init(next(..).x1) | Nested.java:5:9:5:14 | SSA def(x1) | | Nested.java:8:29:8:57 | SSA capture def(next(..).x1) | Nested.java:5:9:5:14 | SSA def(x1) |
| Nested.java:16:22:16:34 | SSA init(getInt(..).obj) | Nested.java:15:12:15:29 | SSA def(obj) | | Nested.java:16:22:16:34 | SSA capture def(getInt(..).obj) | Nested.java:15:12:15:29 | SSA def(obj) |
| Nested.java:19:27:22:7 | SSA init(getInt(..).hash) | Nested.java:16:15:16:34 | SSA def(hash) | | Nested.java:19:27:22:7 | SSA capture def(getInt(..).hash) | Nested.java:16:15:16:34 | SSA def(hash) |
| Nested.java:19:27:22:7 | SSA init(getInt(..).x2) | Nested.java:17:9:17:15 | SSA def(x2) | | Nested.java:19:27:22:7 | SSA capture def(getInt(..).x2) | Nested.java:17:9:17:15 | SSA def(x2) |
| Nested.java:20:27:20:39 | SSA init(getInt(..).obj) | Nested.java:15:12:15:29 | SSA def(obj) | | Nested.java:20:27:20:39 | SSA capture def(getInt(..).obj) | Nested.java:15:12:15:29 | SSA def(obj) |
| Nested.java:30:23:30:36 | SSA init(getInt(..).obj2) | Nested.java:30:5:30:37 | SSA phi(obj2) | | Nested.java:30:23:30:36 | SSA capture def(getInt(..).obj2) | Nested.java:30:5:30:37 | SSA phi(obj2) |
| Nested.java:37:20:37:25 | SSA init(getInt(..).x3) | Nested.java:36:7:36:12 | SSA def(x3) | | Nested.java:37:20:37:25 | SSA capture def(getInt(..).x3) | Nested.java:36:7:36:12 | SSA def(x3) |
| Nested.java:40:20:40:25 | SSA init(getInt(..).x3) | Nested.java:39:7:39:12 | SSA def(x3) | | Nested.java:40:20:40:25 | SSA capture def(getInt(..).x3) | Nested.java:39:7:39:12 | SSA def(x3) |

View File

@@ -1,6 +1,6 @@
import java import java
import semmle.code.java.dataflow.SSA import semmle.code.java.dataflow.SSA
from SsaImplicitInit closure, SsaVariable captured from SsaCapturedDefinition closure, SsaDefinition captured
where closure.captures(captured) where closure.captures(captured)
select closure, captured select closure, captured

View File

@@ -1,43 +1,43 @@
| Fields.java:12:19:21:3 | SSA init(this.xs) | Fields.java:13:15:13:16 | xs | | Fields.java:12:19:21:3 | SSA entry def(this.xs) | Fields.java:13:15:13:16 | xs |
| Fields.java:14:5:14:9 | SSA impl upd[nonlocal](this.xs) | Fields.java:15:9:15:10 | xs | | Fields.java:14:5:14:9 | SSA call def(this.xs) | Fields.java:15:9:15:10 | xs |
| Fields.java:15:5:15:10 | SSA def(x) | Fields.java:16:9:16:9 | x | | Fields.java:15:5:15:10 | SSA def(x) | Fields.java:16:9:16:9 | x |
| Fields.java:17:7:17:11 | SSA impl upd[nonlocal](this.xs) | Fields.java:18:9:18:15 | this.xs | | Fields.java:17:7:17:11 | SSA call def(this.xs) | Fields.java:18:9:18:15 | this.xs |
| Fields.java:18:5:18:16 | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs | | Fields.java:18:5:18:16 | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs |
| Fields.java:19:5:19:19 | SSA def(this.xs) | Fields.java:20:9:20:10 | xs | | Fields.java:19:5:19:19 | SSA def(this.xs) | Fields.java:20:9:20:10 | xs |
| Fields.java:23:19:49:3 | SSA init(Fields.stat) | Fields.java:27:15:27:18 | stat | | Fields.java:23:19:49:3 | SSA entry def(Fields.stat) | Fields.java:27:15:27:18 | stat |
| Fields.java:23:19:49:3 | SSA init(this.xs) | Fields.java:26:15:26:16 | xs | | Fields.java:23:19:49:3 | SSA entry def(this.xs) | Fields.java:26:15:26:16 | xs |
| Fields.java:24:12:24:27 | SSA def(f) | Fields.java:25:15:25:15 | f | | Fields.java:24:12:24:27 | SSA def(f) | Fields.java:25:15:25:15 | f |
| Fields.java:24:12:24:27 | SSA impl upd[explicit qualifier](f.xs) | Fields.java:25:15:25:18 | f.xs | | Fields.java:24:12:24:27 | SSA qualifier def(f.xs) | Fields.java:25:15:25:18 | f.xs |
| Fields.java:24:16:24:27 | SSA impl upd[nonlocal](Fields.stat) | Fields.java:27:15:27:18 | stat | | Fields.java:24:16:24:27 | SSA call def(Fields.stat) | Fields.java:27:15:27:18 | stat |
| Fields.java:28:5:28:12 | SSA impl upd[nonlocal](Fields.stat) | Fields.java:31:9:31:12 | stat | | Fields.java:28:5:28:12 | SSA call def(Fields.stat) | Fields.java:31:9:31:12 | stat |
| Fields.java:28:5:28:12 | SSA impl upd[nonlocal](f.xs) | Fields.java:29:9:29:12 | f.xs | | Fields.java:28:5:28:12 | SSA call def(f.xs) | Fields.java:29:9:29:12 | f.xs |
| Fields.java:28:5:28:12 | SSA impl upd[nonlocal](this.xs) | Fields.java:30:9:30:10 | xs | | Fields.java:28:5:28:12 | SSA call def(this.xs) | Fields.java:30:9:30:10 | xs |
| Fields.java:32:5:32:9 | SSA impl upd[nonlocal](Fields.stat) | Fields.java:35:9:35:12 | stat | | Fields.java:32:5:32:9 | SSA call def(Fields.stat) | Fields.java:35:9:35:12 | stat |
| Fields.java:32:5:32:9 | SSA impl upd[nonlocal](f.xs) | Fields.java:33:9:33:12 | f.xs | | Fields.java:32:5:32:9 | SSA call def(f.xs) | Fields.java:33:9:33:12 | f.xs |
| Fields.java:32:5:32:9 | SSA impl upd[nonlocal](this.xs) | Fields.java:34:9:34:10 | xs | | Fields.java:32:5:32:9 | SSA call def(this.xs) | Fields.java:34:9:34:10 | xs |
| Fields.java:36:5:36:19 | SSA def(this.xs) | Fields.java:38:9:38:10 | xs | | Fields.java:36:5:36:19 | SSA def(this.xs) | Fields.java:38:9:38:10 | xs |
| Fields.java:39:5:39:21 | SSA def(f.xs) | Fields.java:40:9:40:12 | f.xs | | Fields.java:39:5:39:21 | SSA def(f.xs) | Fields.java:40:9:40:12 | f.xs |
| Fields.java:41:5:41:10 | SSA def(z) | Fields.java:42:9:42:9 | z | | Fields.java:41:5:41:10 | SSA def(z) | Fields.java:42:9:42:9 | z |
| Fields.java:43:7:43:22 | SSA def(f) | Fields.java:44:9:44:9 | f | | Fields.java:43:7:43:22 | SSA def(f) | Fields.java:44:9:44:9 | f |
| Fields.java:43:7:43:22 | SSA impl upd[explicit qualifier](f.xs) | Fields.java:44:9:44:12 | f.xs | | Fields.java:43:7:43:22 | SSA qualifier def(f.xs) | Fields.java:44:9:44:12 | f.xs |
| Fields.java:43:11:43:22 | SSA impl upd[nonlocal](Fields.stat) | Fields.java:48:9:48:12 | stat | | Fields.java:43:11:43:22 | SSA call def(Fields.stat) | Fields.java:48:9:48:12 | stat |
| Fields.java:44:5:44:13 | SSA phi(Fields.stat) | Fields.java:48:9:48:12 | stat | | Fields.java:44:5:44:13 | SSA phi(Fields.stat) | Fields.java:48:9:48:12 | stat |
| Fields.java:44:5:44:13 | SSA phi(f) | Fields.java:44:9:44:9 | f | | Fields.java:44:5:44:13 | SSA phi(f) | Fields.java:44:9:44:9 | f |
| Fields.java:44:5:44:13 | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs | | Fields.java:44:5:44:13 | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs |
| Fields.java:45:5:45:16 | SSA impl upd[nonlocal](Fields.stat) | Fields.java:48:9:48:12 | stat | | Fields.java:45:5:45:16 | SSA call def(Fields.stat) | Fields.java:48:9:48:12 | stat |
| Nested.java:8:29:8:57 | SSA init(next(..).p1) | Nested.java:8:38:8:39 | p1 | | Nested.java:8:29:8:57 | SSA capture def(next(..).p1) | Nested.java:8:38:8:39 | p1 |
| Nested.java:8:29:8:57 | SSA init(next(..).x1) | Nested.java:8:43:8:44 | x1 | | Nested.java:8:29:8:57 | SSA capture def(next(..).x1) | Nested.java:8:43:8:44 | x1 |
| Nested.java:16:22:16:34 | SSA init(getInt(..).obj) | Nested.java:16:22:16:24 | obj | | Nested.java:16:22:16:34 | SSA capture def(getInt(..).obj) | Nested.java:16:22:16:24 | obj |
| Nested.java:18:15:23:5 | SSA def(h2) | Nested.java:25:9:25:10 | h2 | | Nested.java:18:15:23:5 | SSA def(h2) | Nested.java:25:9:25:10 | h2 |
| Nested.java:19:27:22:7 | SSA init(getInt(..).hash) | Nested.java:21:21:21:24 | hash | | Nested.java:19:27:22:7 | SSA capture def(getInt(..).hash) | Nested.java:21:21:21:24 | hash |
| Nested.java:19:27:22:7 | SSA init(getInt(..).x2) | Nested.java:21:16:21:17 | x2 | | Nested.java:19:27:22:7 | SSA capture def(getInt(..).x2) | Nested.java:21:16:21:17 | x2 |
| Nested.java:20:19:20:39 | SSA def(hnest) | Nested.java:21:37:21:41 | hnest | | Nested.java:20:19:20:39 | SSA def(hnest) | Nested.java:21:37:21:41 | hnest |
| Nested.java:20:27:20:39 | SSA init(getInt(..).obj) | Nested.java:20:27:20:29 | obj | | Nested.java:20:27:20:39 | SSA capture def(getInt(..).obj) | Nested.java:20:27:20:29 | obj |
| Nested.java:30:23:30:36 | SSA init(getInt(..).obj2) | Nested.java:30:23:30:26 | obj2 | | Nested.java:30:23:30:36 | SSA capture def(getInt(..).obj2) | Nested.java:30:23:30:26 | obj2 |
| Nested.java:33:29:42:3 | SSA init(p3) | Nested.java:35:9:35:10 | p3 | | Nested.java:33:29:42:3 | SSA param(p3) | Nested.java:35:9:35:10 | p3 |
| Nested.java:37:20:37:25 | SSA init(getInt(..).x3) | Nested.java:37:20:37:21 | x3 | | Nested.java:37:20:37:25 | SSA capture def(getInt(..).x3) | Nested.java:37:20:37:21 | x3 |
| Nested.java:40:20:40:25 | SSA init(getInt(..).x3) | Nested.java:40:20:40:21 | x3 | | Nested.java:40:20:40:25 | SSA capture def(getInt(..).x3) | Nested.java:40:20:40:21 | x3 |
| Test.java:4:19:32:2 | SSA init(param) | Test.java:9:7:9:11 | param | | Test.java:4:19:32:2 | SSA param(param) | Test.java:9:7:9:11 | param |
| Test.java:6:7:6:11 | SSA def(x) | Test.java:10:4:10:4 | x | | Test.java:6:7:6:11 | SSA def(x) | Test.java:10:4:10:4 | x |
| Test.java:6:7:6:11 | SSA def(x) | Test.java:20:10:20:10 | x | | Test.java:6:7:6:11 | SSA def(x) | Test.java:20:10:20:10 | x |
| Test.java:10:4:10:6 | SSA def(x) | Test.java:11:10:11:10 | x | | Test.java:10:4:10:6 | SSA def(x) | Test.java:11:10:11:10 | x |
@@ -58,15 +58,12 @@
| Test.java:27:25:27:27 | SSA def(i) | Test.java:27:19:27:19 | i | | Test.java:27:25:27:27 | SSA def(i) | Test.java:27:19:27:19 | i |
| Test.java:28:4:28:9 | SSA def(x) | Test.java:28:4:28:4 | x | | Test.java:28:4:28:9 | SSA def(x) | Test.java:28:4:28:4 | x |
| Test.java:28:4:28:9 | SSA def(x) | Test.java:31:10:31:10 | x | | Test.java:28:4:28:9 | SSA def(x) | Test.java:31:10:31:10 | x |
| TestInstanceOfPattern.java:3:24:9:2 | SSA init(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj | | TestInstanceOfPattern.java:3:24:9:2 | SSA param(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj |
| TestInstanceOfPattern.java:4:29:4:29 | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s | | TestInstanceOfPattern.java:4:29:4:29 | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s |
| TestInstanceOfPattern.java:7:8:7:8 | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:7:8:7:8 | s | | TestInstanceOfPattern.java:10:25:16:2 | SSA param(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj |
| TestInstanceOfPattern.java:10:25:16:2 | SSA init(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj |
| TestInstanceOfPattern.java:11:31:11:31 | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s | | TestInstanceOfPattern.java:11:31:11:31 | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s |
| TestInstanceOfPattern.java:12:8:12:8 | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:12:8:12:8 | s | | TestInstanceOfPattern.java:17:25:23:2 | SSA param(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj |
| TestInstanceOfPattern.java:17:25:23:2 | SSA init(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj |
| TestInstanceOfPattern.java:18:29:18:29 | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s | | TestInstanceOfPattern.java:18:29:18:29 | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s |
| TestInstanceOfPattern.java:21:8:21:8 | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:21:8:21:8 | s | | TestInstanceOfPattern.java:24:25:30:2 | SSA entry def(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s |
| TestInstanceOfPattern.java:24:25:30:2 | SSA init(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj | | TestInstanceOfPattern.java:24:25:30:2 | SSA entry def(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s |
| TestInstanceOfPattern.java:24:25:30:2 | SSA init(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s | | TestInstanceOfPattern.java:24:25:30:2 | SSA param(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj |
| TestInstanceOfPattern.java:24:25:30:2 | SSA init(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s |

View File

@@ -1,6 +1,6 @@
import java import java
import semmle.code.java.dataflow.SSA import semmle.code.java.dataflow.SSA
from SsaVariable ssa, VarRead use from SsaDefinition ssa, VarRead use
where use = ssa.getAFirstUse() where use = ssaGetAFirstUse(ssa)
select ssa, use select ssa, use

View File

@@ -1,53 +1,53 @@
| Fields.java:13:5:13:17 | x | Fields.java:15:5:15:10 | ...=... | SSA def(x) | | Fields.java:13:5:13:17 | x | Fields.java:15:5:15:10 | ...=... | SSA def(x) |
| Fields.java:13:15:13:16 | this.xs | Fields.java:12:19:21:3 | { ... } | SSA init(this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:12:19:21:3 | { ... } | SSA entry def(this.xs) |
| Fields.java:13:15:13:16 | this.xs | Fields.java:14:5:14:9 | upd(...) | SSA impl upd[nonlocal](this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:14:5:14:9 | upd(...) | SSA call def(this.xs) |
| Fields.java:13:15:13:16 | this.xs | Fields.java:17:7:17:11 | upd(...) | SSA impl upd[nonlocal](this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:17:7:17:11 | upd(...) | SSA call def(this.xs) |
| Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | <Expr>; | SSA phi(this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | <Expr>; | SSA phi(this.xs) |
| Fields.java:13:15:13:16 | this.xs | Fields.java:19:5:19:19 | ...=... | SSA def(this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:19:5:19:19 | ...=... | SSA def(this.xs) |
| Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) |
| Fields.java:24:5:24:28 | f | Fields.java:43:7:43:22 | ...=... | SSA def(f) | | Fields.java:24:5:24:28 | f | Fields.java:43:7:43:22 | ...=... | SSA def(f) |
| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f) | | Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f) |
| Fields.java:25:15:25:18 | f.xs | Fields.java:24:12:24:27 | f | SSA impl upd[explicit qualifier](f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:24:12:24:27 | f | SSA qualifier def(f.xs) |
| Fields.java:25:15:25:18 | f.xs | Fields.java:28:5:28:12 | f(...) | SSA impl upd[nonlocal](f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(f.xs) |
| Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA impl upd[nonlocal](f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(f.xs) |
| Fields.java:25:15:25:18 | f.xs | Fields.java:39:5:39:21 | ...=... | SSA def(f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:39:5:39:21 | ...=... | SSA def(f.xs) |
| Fields.java:25:15:25:18 | f.xs | Fields.java:43:7:43:22 | ...=... | SSA impl upd[explicit qualifier](f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:43:7:43:22 | ...=... | SSA qualifier def(f.xs) |
| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f.xs) |
| Fields.java:26:5:26:17 | z | Fields.java:41:5:41:10 | ...=... | SSA def(z) | | Fields.java:26:5:26:17 | z | Fields.java:41:5:41:10 | ...=... | SSA def(z) |
| Fields.java:26:15:26:16 | this.xs | Fields.java:23:19:49:3 | { ... } | SSA init(this.xs) | | Fields.java:26:15:26:16 | this.xs | Fields.java:23:19:49:3 | { ... } | SSA entry def(this.xs) |
| Fields.java:26:15:26:16 | this.xs | Fields.java:28:5:28:12 | f(...) | SSA impl upd[nonlocal](this.xs) | | Fields.java:26:15:26:16 | this.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(this.xs) |
| Fields.java:26:15:26:16 | this.xs | Fields.java:32:5:32:9 | f(...) | SSA impl upd[nonlocal](this.xs) | | Fields.java:26:15:26:16 | this.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(this.xs) |
| Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | | Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:23:19:49:3 | { ... } | SSA init(Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:23:19:49:3 | { ... } | SSA entry def(Fields.stat) |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:24:16:24:27 | new Fields(...) | SSA impl upd[nonlocal](Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:24:16:24:27 | new Fields(...) | SSA call def(Fields.stat) |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:28:5:28:12 | f(...) | SSA impl upd[nonlocal](Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:28:5:28:12 | f(...) | SSA call def(Fields.stat) |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:32:5:32:9 | f(...) | SSA impl upd[nonlocal](Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:32:5:32:9 | f(...) | SSA call def(Fields.stat) |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:43:11:43:22 | new Fields(...) | SSA impl upd[nonlocal](Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:43:11:43:22 | new Fields(...) | SSA call def(Fields.stat) |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:44:5:44:13 | <Expr>; | SSA phi(Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:44:5:44:13 | <Expr>; | SSA phi(Fields.stat) |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:45:5:45:16 | new Fields(...) | SSA impl upd[nonlocal](Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:45:5:45:16 | new Fields(...) | SSA call def(Fields.stat) |
| Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:29:8:57 | { ... } | SSA init(next(..).p1) | | Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).p1) |
| Nested.java:4:26:4:31 | p1 | Nested.java:4:34:10:3 | { ... } | SSA init(p1) | | Nested.java:4:26:4:31 | p1 | Nested.java:4:34:10:3 | { ... } | SSA param(p1) |
| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA init(next(..).x1) | | Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) |
| Nested.java:5:5:5:15 | x1 | Nested.java:5:9:5:14 | x1 | SSA def(x1) | | Nested.java:5:5:5:15 | x1 | Nested.java:5:9:5:14 | x1 | SSA def(x1) |
| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | { ... } | SSA init(getInt(..).obj) | | Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | { ... } | SSA capture def(getInt(..).obj) |
| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | { ... } | SSA init(getInt(..).obj) | | Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | { ... } | SSA capture def(getInt(..).obj) |
| Nested.java:15:5:15:30 | obj | Nested.java:15:12:15:29 | obj | SSA def(obj) | | Nested.java:15:5:15:30 | obj | Nested.java:15:12:15:29 | obj | SSA def(obj) |
| Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:27:22:7 | { ... } | SSA init(getInt(..).hash) | | Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).hash) |
| Nested.java:16:5:16:35 | hash | Nested.java:16:15:16:34 | hash | SSA def(hash) | | Nested.java:16:5:16:35 | hash | Nested.java:16:15:16:34 | hash | SSA def(hash) |
| Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:27:22:7 | { ... } | SSA init(getInt(..).x2) | | Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).x2) |
| Nested.java:17:5:17:16 | x2 | Nested.java:17:9:17:15 | x2 | SSA def(x2) | | Nested.java:17:5:17:16 | x2 | Nested.java:17:9:17:15 | x2 | SSA def(x2) |
| Nested.java:18:5:23:6 | h2 | Nested.java:18:15:23:5 | h2 | SSA def(h2) | | Nested.java:18:5:23:6 | h2 | Nested.java:18:15:23:5 | h2 | SSA def(h2) |
| Nested.java:20:9:20:40 | hnest | Nested.java:20:19:20:39 | hnest | SSA def(hnest) | | Nested.java:20:9:20:40 | hnest | Nested.java:20:19:20:39 | hnest | SSA def(hnest) |
| Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | { ... } | SSA init(getInt(..).obj2) | | Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | { ... } | SSA capture def(getInt(..).obj2) |
| Nested.java:24:5:24:31 | obj2 | Nested.java:26:7:26:25 | ...=... | SSA def(obj2) | | Nested.java:24:5:24:31 | obj2 | Nested.java:26:7:26:25 | ...=... | SSA def(obj2) |
| Nested.java:24:5:24:31 | obj2 | Nested.java:28:7:28:25 | ...=... | SSA def(obj2) | | Nested.java:24:5:24:31 | obj2 | Nested.java:28:7:28:25 | ...=... | SSA def(obj2) |
| Nested.java:24:5:24:31 | obj2 | Nested.java:30:5:30:37 | var ...; | SSA phi(obj2) | | Nested.java:24:5:24:31 | obj2 | Nested.java:30:5:30:37 | var ...; | SSA phi(obj2) |
| Nested.java:33:21:33:26 | p3 | Nested.java:33:29:42:3 | { ... } | SSA init(p3) | | Nested.java:33:21:33:26 | p3 | Nested.java:33:29:42:3 | { ... } | SSA param(p3) |
| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:20:37:25 | { ... } | SSA init(getInt(..).x3) | | Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:20:37:25 | { ... } | SSA capture def(getInt(..).x3) |
| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:20:40:25 | { ... } | SSA init(getInt(..).x3) | | Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:20:40:25 | { ... } | SSA capture def(getInt(..).x3) |
| Nested.java:34:5:34:11 | x3 | Nested.java:36:7:36:12 | ...=... | SSA def(x3) | | Nested.java:34:5:34:11 | x3 | Nested.java:36:7:36:12 | ...=... | SSA def(x3) |
| Nested.java:34:5:34:11 | x3 | Nested.java:39:7:39:12 | ...=... | SSA def(x3) | | Nested.java:34:5:34:11 | x3 | Nested.java:39:7:39:12 | ...=... | SSA def(x3) |
| Test.java:4:8:4:16 | param | Test.java:4:19:32:2 | { ... } | SSA init(param) | | Test.java:4:8:4:16 | param | Test.java:4:19:32:2 | { ... } | SSA param(param) |
| Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | SSA phi(param) | | Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | SSA phi(param) |
| Test.java:4:8:4:16 | param | Test.java:21:8:21:14 | ...++ | SSA def(param) | | Test.java:4:8:4:16 | param | Test.java:21:8:21:14 | ...++ | SSA def(param) |
| Test.java:6:3:6:12 | x | Test.java:6:7:6:11 | x | SSA def(x) | | Test.java:6:3:6:12 | x | Test.java:6:7:6:11 | x | SSA def(x) |
@@ -65,14 +65,11 @@
| Test.java:27:8:27:16 | i | Test.java:27:12:27:16 | i | SSA def(i) | | Test.java:27:8:27:16 | i | Test.java:27:12:27:16 | i | SSA def(i) |
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | | Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) |
| Test.java:27:8:27:16 | i | Test.java:27:25:27:27 | ...++ | SSA def(i) | | Test.java:27:8:27:16 | i | Test.java:27:25:27:27 | ...++ | SSA def(i) |
| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | { ... } | SSA init(obj) | | TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | { ... } | SSA param(obj) |
| TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) | | TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) |
| TestInstanceOfPattern.java:7:8:7:8 | this.s | TestInstanceOfPattern.java:7:8:7:8 | s | SSA impl upd[untracked](this.s) | | TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | { ... } | SSA param(obj) |
| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | { ... } | SSA init(obj) |
| TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) | | TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) |
| TestInstanceOfPattern.java:12:8:12:8 | this.s | TestInstanceOfPattern.java:12:8:12:8 | s | SSA impl upd[untracked](this.s) | | TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | { ... } | SSA param(obj) |
| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | { ... } | SSA init(obj) |
| TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | | TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) |
| TestInstanceOfPattern.java:21:8:21:8 | this.s | TestInstanceOfPattern.java:21:8:21:8 | s | SSA impl upd[untracked](this.s) | | TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA param(obj) |
| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA init(obj) | | TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) |
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA init(this.s) |

View File

@@ -1,7 +1,7 @@
import java import java
import semmle.code.java.dataflow.SSA import semmle.code.java.dataflow.SSA
from SsaVariable ssa, SsaSourceVariable v, string s from SsaDefinition ssa, SsaSourceVariable v, string s
where where
ssa.getSourceVariable() = v and ssa.getSourceVariable() = v and
( (
@@ -9,4 +9,4 @@ where
or or
not exists(ssa.toString()) and s = "error" not exists(ssa.toString()) and s = "error"
) )
select v, ssa.getCfgNode(), s select v, ssa.getControlFlowNode(), s

View File

@@ -1,6 +1,6 @@
import java import java
import semmle.code.java.dataflow.SSA import semmle.code.java.dataflow.SSA
from SsaPhiNode ssa, SsaSourceVariable v, SsaVariable phiInput from SsaPhiDefinition ssa, SsaSourceVariable v, SsaDefinition phiInput
where ssa.getAPhiInput() = phiInput and ssa.getSourceVariable() = v where ssa.getAnInput() = phiInput and ssa.getSourceVariable() = v
select v, ssa.getCfgNode(), phiInput.getCfgNode() select v, ssa.getControlFlowNode(), phiInput.getControlFlowNode()

View File

@@ -1,6 +1,6 @@
| Fields.java:13:5:13:17 | x | Fields.java:15:5:15:10 | ...=... | SSA def(x) | Fields.java:16:9:16:9 | x | | Fields.java:13:5:13:17 | x | Fields.java:15:5:15:10 | ...=... | SSA def(x) | Fields.java:16:9:16:9 | x |
| Fields.java:13:15:13:16 | this.xs | Fields.java:12:19:21:3 | { ... } | SSA init(this.xs) | Fields.java:13:15:13:16 | xs | | Fields.java:13:15:13:16 | this.xs | Fields.java:12:19:21:3 | { ... } | SSA entry def(this.xs) | Fields.java:13:15:13:16 | xs |
| Fields.java:13:15:13:16 | this.xs | Fields.java:14:5:14:9 | upd(...) | SSA impl upd[nonlocal](this.xs) | Fields.java:15:9:15:10 | xs | | Fields.java:13:15:13:16 | this.xs | Fields.java:14:5:14:9 | upd(...) | SSA call def(this.xs) | Fields.java:15:9:15:10 | xs |
| Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | <Expr>; | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs | | Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | <Expr>; | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs |
| Fields.java:13:15:13:16 | this.xs | Fields.java:19:5:19:19 | ...=... | SSA def(this.xs) | Fields.java:20:9:20:10 | xs | | Fields.java:13:15:13:16 | this.xs | Fields.java:19:5:19:19 | ...=... | SSA def(this.xs) | Fields.java:20:9:20:10 | xs |
| Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:25:15:25:15 | f | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:25:15:25:15 | f |
@@ -12,39 +12,39 @@
| Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:40:9:40:9 | f | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:40:9:40:9 | f |
| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f) | Fields.java:44:9:44:9 | f | | Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f) | Fields.java:44:9:44:9 | f |
| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f) | Fields.java:46:9:46:9 | f | | Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f) | Fields.java:46:9:46:9 | f |
| Fields.java:25:15:25:18 | f.xs | Fields.java:24:12:24:27 | f | SSA impl upd[explicit qualifier](f.xs) | Fields.java:25:15:25:18 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:24:12:24:27 | f | SSA qualifier def(f.xs) | Fields.java:25:15:25:18 | f.xs |
| Fields.java:25:15:25:18 | f.xs | Fields.java:28:5:28:12 | f(...) | SSA impl upd[nonlocal](f.xs) | Fields.java:29:9:29:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(f.xs) | Fields.java:29:9:29:12 | f.xs |
| Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA impl upd[nonlocal](f.xs) | Fields.java:33:9:33:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(f.xs) | Fields.java:33:9:33:12 | f.xs |
| Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA impl upd[nonlocal](f.xs) | Fields.java:37:9:37:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(f.xs) | Fields.java:37:9:37:12 | f.xs |
| Fields.java:25:15:25:18 | f.xs | Fields.java:39:5:39:21 | ...=... | SSA def(f.xs) | Fields.java:40:9:40:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:39:5:39:21 | ...=... | SSA def(f.xs) | Fields.java:40:9:40:12 | f.xs |
| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs |
| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f.xs) | Fields.java:46:9:46:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | <Expr>; | SSA phi(f.xs) | Fields.java:46:9:46:12 | f.xs |
| Fields.java:26:5:26:17 | z | Fields.java:41:5:41:10 | ...=... | SSA def(z) | Fields.java:42:9:42:9 | z | | Fields.java:26:5:26:17 | z | Fields.java:41:5:41:10 | ...=... | SSA def(z) | Fields.java:42:9:42:9 | z |
| Fields.java:26:15:26:16 | this.xs | Fields.java:23:19:49:3 | { ... } | SSA init(this.xs) | Fields.java:26:15:26:16 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:23:19:49:3 | { ... } | SSA entry def(this.xs) | Fields.java:26:15:26:16 | xs |
| Fields.java:26:15:26:16 | this.xs | Fields.java:28:5:28:12 | f(...) | SSA impl upd[nonlocal](this.xs) | Fields.java:30:9:30:10 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(this.xs) | Fields.java:30:9:30:10 | xs |
| Fields.java:26:15:26:16 | this.xs | Fields.java:32:5:32:9 | f(...) | SSA impl upd[nonlocal](this.xs) | Fields.java:34:9:34:10 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(this.xs) | Fields.java:34:9:34:10 | xs |
| Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | Fields.java:38:9:38:10 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | Fields.java:38:9:38:10 | xs |
| Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | Fields.java:41:9:41:10 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | Fields.java:41:9:41:10 | xs |
| Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | Fields.java:47:9:47:10 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | Fields.java:47:9:47:10 | xs |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:24:16:24:27 | new Fields(...) | SSA impl upd[nonlocal](Fields.stat) | Fields.java:27:15:27:18 | stat | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:24:16:24:27 | new Fields(...) | SSA call def(Fields.stat) | Fields.java:27:15:27:18 | stat |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:28:5:28:12 | f(...) | SSA impl upd[nonlocal](Fields.stat) | Fields.java:31:9:31:12 | stat | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:28:5:28:12 | f(...) | SSA call def(Fields.stat) | Fields.java:31:9:31:12 | stat |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:32:5:32:9 | f(...) | SSA impl upd[nonlocal](Fields.stat) | Fields.java:35:9:35:12 | stat | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:32:5:32:9 | f(...) | SSA call def(Fields.stat) | Fields.java:35:9:35:12 | stat |
| Fields.java:27:15:27:18 | Fields.stat | Fields.java:45:5:45:16 | new Fields(...) | SSA impl upd[nonlocal](Fields.stat) | Fields.java:48:9:48:12 | stat | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:45:5:45:16 | new Fields(...) | SSA call def(Fields.stat) | Fields.java:48:9:48:12 | stat |
| Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:29:8:57 | { ... } | SSA init(next(..).p1) | Nested.java:8:38:8:39 | p1 | | Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).p1) | Nested.java:8:38:8:39 | p1 |
| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA init(next(..).x1) | Nested.java:8:43:8:44 | x1 | | Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) | Nested.java:8:43:8:44 | x1 |
| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA init(next(..).x1) | Nested.java:8:48:8:49 | x1 | | Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) | Nested.java:8:48:8:49 | x1 |
| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA init(next(..).x1) | Nested.java:8:53:8:54 | x1 | | Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) | Nested.java:8:53:8:54 | x1 |
| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | { ... } | SSA init(getInt(..).obj) | Nested.java:16:22:16:24 | obj | | Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | { ... } | SSA capture def(getInt(..).obj) | Nested.java:16:22:16:24 | obj |
| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | { ... } | SSA init(getInt(..).obj) | Nested.java:20:27:20:29 | obj | | Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | { ... } | SSA capture def(getInt(..).obj) | Nested.java:20:27:20:29 | obj |
| Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:27:22:7 | { ... } | SSA init(getInt(..).hash) | Nested.java:21:21:21:24 | hash | | Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).hash) | Nested.java:21:21:21:24 | hash |
| Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:27:22:7 | { ... } | SSA init(getInt(..).x2) | Nested.java:21:16:21:17 | x2 | | Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).x2) | Nested.java:21:16:21:17 | x2 |
| Nested.java:18:5:23:6 | h2 | Nested.java:18:15:23:5 | h2 | SSA def(h2) | Nested.java:25:9:25:10 | h2 | | Nested.java:18:5:23:6 | h2 | Nested.java:18:15:23:5 | h2 | SSA def(h2) | Nested.java:25:9:25:10 | h2 |
| Nested.java:20:9:20:40 | hnest | Nested.java:20:19:20:39 | hnest | SSA def(hnest) | Nested.java:21:37:21:41 | hnest | | Nested.java:20:9:20:40 | hnest | Nested.java:20:19:20:39 | hnest | SSA def(hnest) | Nested.java:21:37:21:41 | hnest |
| Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | { ... } | SSA init(getInt(..).obj2) | Nested.java:30:23:30:26 | obj2 | | Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | { ... } | SSA capture def(getInt(..).obj2) | Nested.java:30:23:30:26 | obj2 |
| Nested.java:33:21:33:26 | p3 | Nested.java:33:29:42:3 | { ... } | SSA init(p3) | Nested.java:35:9:35:10 | p3 | | Nested.java:33:21:33:26 | p3 | Nested.java:33:29:42:3 | { ... } | SSA param(p3) | Nested.java:35:9:35:10 | p3 |
| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:20:37:25 | { ... } | SSA init(getInt(..).x3) | Nested.java:37:20:37:21 | x3 | | Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:20:37:25 | { ... } | SSA capture def(getInt(..).x3) | Nested.java:37:20:37:21 | x3 |
| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:20:40:25 | { ... } | SSA init(getInt(..).x3) | Nested.java:40:20:40:21 | x3 | | Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:20:40:25 | { ... } | SSA capture def(getInt(..).x3) | Nested.java:40:20:40:21 | x3 |
| Test.java:4:8:4:16 | param | Test.java:4:19:32:2 | { ... } | SSA init(param) | Test.java:9:7:9:11 | param | | Test.java:4:8:4:16 | param | Test.java:4:19:32:2 | { ... } | SSA param(param) | Test.java:9:7:9:11 | param |
| Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | SSA phi(param) | Test.java:21:8:21:12 | param | | Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | SSA phi(param) | Test.java:21:8:21:12 | param |
| Test.java:6:3:6:12 | x | Test.java:6:7:6:11 | x | SSA def(x) | Test.java:10:4:10:4 | x | | Test.java:6:3:6:12 | x | Test.java:6:7:6:11 | x | SSA def(x) | Test.java:10:4:10:4 | x |
| Test.java:6:3:6:12 | x | Test.java:10:4:10:6 | ...++ | SSA def(x) | Test.java:11:10:11:10 | x | | Test.java:6:3:6:12 | x | Test.java:10:4:10:6 | ...++ | SSA def(x) | Test.java:11:10:11:10 | x |
@@ -58,17 +58,14 @@
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:19:27:19 | i | | Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:19:27:19 | i |
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:25:27:25 | i | | Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:25:27:25 | i |
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:28:9:28:9 | i | | Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:28:9:28:9 | i |
| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | { ... } | SSA init(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj | | TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj |
| TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s | | TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s |
| TestInstanceOfPattern.java:7:8:7:8 | this.s | TestInstanceOfPattern.java:7:8:7:8 | s | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:7:8:7:8 | s | | TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj |
| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | { ... } | SSA init(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj |
| TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s | | TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s |
| TestInstanceOfPattern.java:12:8:12:8 | this.s | TestInstanceOfPattern.java:12:8:12:8 | s | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:12:8:12:8 | s | | TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj |
| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | { ... } | SSA init(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj |
| TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s | | TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s |
| TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:19:8:19:8 | s | | TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:19:8:19:8 | s |
| TestInstanceOfPattern.java:21:8:21:8 | this.s | TestInstanceOfPattern.java:21:8:21:8 | s | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:21:8:21:8 | s | | TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj |
| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA init(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj | | TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s |
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA init(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s | | TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s |
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA init(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s | | TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) | TestInstanceOfPattern.java:28:8:28:8 | s |
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA init(this.s) | TestInstanceOfPattern.java:28:8:28:8 | s |

View File

@@ -1,6 +1,6 @@
import java import java
import semmle.code.java.dataflow.SSA import semmle.code.java.dataflow.SSA
from SsaVariable ssa, SsaSourceVariable v, Expr use from SsaDefinition ssa, SsaSourceVariable v, Expr use
where use = ssa.getAUse() and ssa.getSourceVariable() = v where use = ssa.getARead() and ssa.getSourceVariable() = v
select v, ssa.getCfgNode(), ssa.toString(), use select v, ssa.getControlFlowNode(), ssa.toString(), use

View File

@@ -1617,6 +1617,9 @@ module Make<
/** A static single assignment (SSA) definition. */ /** A static single assignment (SSA) definition. */
class SsaDefinition extends FinalDefinition { class SsaDefinition extends FinalDefinition {
/** Gets a textual representation of this SSA definition. */
string toString() { result = super.toString() }
/** /**
* Gets the control flow node of this SSA definition. * Gets the control flow node of this SSA definition.
* *
@@ -1708,6 +1711,8 @@ module Make<
class SsaParameterInit extends SsaExplicitWrite { class SsaParameterInit extends SsaExplicitWrite {
SsaParameterInit() { parameterInit(this, _) } SsaParameterInit() { parameterInit(this, _) }
override string toString() { result = "SSA param(" + this.getSourceVariable() + ")" }
/** /**
* Gets the parameter that this definition represents. This is equivalent * Gets the parameter that this definition represents. This is equivalent
* to `getDefinition().isParameterInit(result)` * to `getDefinition().isParameterInit(result)`
@@ -1725,6 +1730,8 @@ module Make<
*/ */
class SsaImplicitWrite extends SsaWriteDefinition { class SsaImplicitWrite extends SsaWriteDefinition {
SsaImplicitWrite() { not explicitWrite(this, _) } SsaImplicitWrite() { not explicitWrite(this, _) }
override string toString() { result = "SSA implicit def(" + this.getSourceVariable() + ")" }
} }
/** /**
@@ -1734,6 +1741,8 @@ module Make<
*/ */
class SsaImplicitEntryDefinition extends SsaImplicitWrite { class SsaImplicitEntryDefinition extends SsaImplicitWrite {
SsaImplicitEntryDefinition() { this.definesAt(_, any(EntryBasicBlock bb), -1) } SsaImplicitEntryDefinition() { this.definesAt(_, any(EntryBasicBlock bb), -1) }
override string toString() { result = "SSA entry def(" + this.getSourceVariable() + ")" }
} }
/** An SSA definition that represents an uncertain variable update. */ /** An SSA definition that represents an uncertain variable update. */
@@ -1761,7 +1770,7 @@ module Make<
* ``` * ```
* a phi definition for `x` is inserted just before the call `puts x`. * a phi definition for `x` is inserted just before the call `puts x`.
*/ */
class SsaPhiDefinition extends SsaDefinition { class SsaPhiDefinition extends SsaDefinition instanceof PhiNode {
/** Holds if `inp` is an input to this phi definition along the edge originating in `bb`. */ /** Holds if `inp` is an input to this phi definition along the edge originating in `bb`. */
predicate hasInputFromBlock(SsaDefinition inp, BasicBlock bb) { predicate hasInputFromBlock(SsaDefinition inp, BasicBlock bb) {
phiHasInputFromBlockCached(this, inp, bb) phiHasInputFromBlockCached(this, inp, bb)