Java: Replace usages of SsaVariable.

This commit is contained in:
Anders Schack-Mulligen
2025-11-07 11:03:46 +01:00
parent 8594ae03df
commit f0bd0346f0
7 changed files with 23 additions and 21 deletions

View File

@@ -108,7 +108,7 @@ Expr clearlyNotNullExpr(Expr reason) {
} }
/** 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.(SsaExplicitWrite).getValue() and src = v.(SsaExplicitWrite).getValue() and
src = clearlyNotNullExpr(reason) src = clearlyNotNullExpr(reason)
@@ -136,7 +136,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 +207,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 +219,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 +228,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 +242,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 +265,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,13 +135,13 @@ 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 SsaPhiDefinition 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.
@@ -157,7 +157,7 @@ private predicate varMaybeNull(SsaVariable v, ControlFlowNode node, string msg,
// 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.(SsaParameterInit).getParameter() = 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
@@ -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

View File

@@ -33,7 +33,7 @@ predicate eqFlowCond = U::eqFlowCond/5;
* `SsaPhiDefinition` in order for the reflexive case of `nonNullSsaFwdStep*(..)` to * `SsaPhiDefinition` in order for the reflexive case of `nonNullSsaFwdStep*(..)` to
* have non-`SsaPhiDefinition` results. * have non-`SsaPhiDefinition` results.
*/ */
private predicate nonNullSsaFwdStep(SsaVariable v, SsaVariable phi) { private predicate nonNullSsaFwdStep(SsaDefinition v, SsaDefinition phi) {
exists(SsaExplicitWrite vnull, SsaPhiDefinition phi0 | phi0 = phi | exists(SsaExplicitWrite vnull, SsaPhiDefinition phi0 | phi0 = phi |
2 = strictcount(phi0.getAnInput()) and 2 = strictcount(phi0.getAnInput()) and
vnull = phi0.getAnInput() and vnull = phi0.getAnInput() and
@@ -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.(SsaExplicitWrite).getValue() = 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)
) )

View File

@@ -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 }
} }
/** /**

View File

@@ -510,7 +510,7 @@ private module Cached {
/** 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(SsaImplicitEntryDefinition init, SsaVariable capturedvar) { predicate captures(SsaImplicitEntryDefinition init, SsaDefinition capturedvar) {
exists(BasicBlock bb, int i | exists(BasicBlock bb, int i |
Ssa::ssaDefReachesUncertainRead(_, capturedvar, bb, i) and Ssa::ssaDefReachesUncertainRead(_, capturedvar, bb, i) and
variableCapture(capturedvar.getSourceVariable(), init.getSourceVariable(), bb, i) variableCapture(capturedvar.getSourceVariable(), init.getSourceVariable(), bb, i)

View File

@@ -17,7 +17,7 @@ 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::SsaPhiDefinition; class SsaPhiNode = Ssa::SsaPhiDefinition;

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