Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c4f0868
Java: Move SSA entry defs to index -1.
aschackmull Oct 21, 2025
f2181ec
Java: Get rid of untracked SSA definitions.
aschackmull Oct 21, 2025
374c772
Java: Remove getAFirstUse in BaseSSA.
aschackmull Oct 21, 2025
79b2f21
SSA: Fix phi defs.
aschackmull Oct 27, 2025
289d337
SSA: Improve toString.
aschackmull Oct 27, 2025
551944b
Java: Add VariableWrite class.
aschackmull Oct 24, 2025
942dc2b
Java: Replace BaseSSA class wrappers with shared code.
aschackmull Oct 23, 2025
d5708fd
Java: Instantiate shared SSA wrappers for main SSA.
aschackmull Nov 5, 2025
154f077
Java: Simplify instantiation of Guards and ControlFlowReachability.
aschackmull Nov 6, 2025
99aa033
Java: Replace usages of isParameterDefinition.
aschackmull Nov 6, 2025
07e6356
Java: Replace getAFirstUse with top-level predicate.
aschackmull Nov 7, 2025
483b2d8
Java: Replace uses of SsaExplicitUpdate.
aschackmull Nov 7, 2025
06df5c0
Java: Introduce SsaCapturedDefinition and replace uses of getAnUltima…
aschackmull Nov 7, 2025
3e43c53
Java: Update some qldoc deprecation notices.
aschackmull Nov 7, 2025
35caede
Java: Replace SsaPhiNode with SsaPhiDefinition.
aschackmull Nov 7, 2025
f4b9efc
Java: Replace getAUse with getARead.
aschackmull Nov 7, 2025
8594ae0
Java: Replace remaining SsaImplicitInit.
aschackmull Nov 7, 2025
f0bd034
Java: Replace usages of SsaVariable.
aschackmull Nov 7, 2025
ee5d65e
Java: Update toString for implicit writes.
aschackmull Nov 7, 2025
5849d85
Java: Deprecate two more SSA classes.
aschackmull Nov 7, 2025
95ac61d
Java: Drop caching of deprecated predicates.
aschackmull Oct 27, 2025
e059ded
Java: Accept toString changes in qltest.
aschackmull Nov 6, 2025
109a5eb
Java: Accept qltest changes due to dropped UntrackedDef.
aschackmull Nov 6, 2025
437ca58
Java: Add change note.
aschackmull Nov 7, 2025
4a58a01
Java: Reinstate useless null check results for fields that are no lon…
aschackmull Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Java: Replace getAUse with getARead.
  • Loading branch information
aschackmull committed Nov 12, 2025
commit f4b9efcdce2a1479377bbc683031e00cc872966a
16 changes: 8 additions & 8 deletions java/ql/lib/semmle/code/java/dataflow/NullGuards.qll
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ Expr enumConstEquality(Expr e, boolean polarity, EnumConstant c) {
}

/** 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.getExpr() = v.getAUse()
result.getExpr() = v.getARead()
}

/**
Expand All @@ -37,8 +37,8 @@ InstanceOfExpr instanceofExpr(SsaVariable v, RefType type) {
*
* Note this includes Kotlin's `==` and `!=` operators, which are value-equality tests.
*/
EqualityTest varEqualityTestExpr(SsaVariable v1, SsaVariable v2, boolean isEqualExpr) {
result.hasOperands(v1.getAUse(), v2.getAUse()) and
EqualityTest varEqualityTestExpr(SsaDefinition v1, SsaDefinition v2, boolean isEqualExpr) {
result.hasOperands(v1.getARead(), v2.getARead()) and
isEqualExpr = result.polarity()
}

Expand Down Expand Up @@ -91,18 +91,18 @@ Expr clearlyNotNullExpr(Expr reason) {
(reason = r1 or reason = r2)
)
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.controls(rval.getBasicBlock(), branch) and
reason = guard and
rval = v.getAUse() and
rval = v.getARead() and
result = rval and
not result = baseNotNullExpr()
)
or
exists(SsaVariable v |
exists(SsaDefinition v |
clearlyNotNull(v, reason) and
result = v.getAUse() and
result = v.getARead() and
not result = baseNotNullExpr()
)
}
Expand Down
14 changes: 7 additions & 7 deletions java/ql/lib/semmle/code/java/dataflow/Nullness.qll
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ private Expr nonEmptyExpr() {
// An array creation with a known positive size is trivially non-empty.
result.(ArrayCreationExpr).getFirstDimensionSize() > 0
or
exists(SsaVariable v |
exists(SsaDefinition v |
// A use of an array variable is non-empty if...
result = v.getAUse() and
result = v.getARead() and
v.getSourceVariable().getType() instanceof Array
|
// ...its definition is non-empty...
Expand All @@ -192,13 +192,13 @@ private Expr nonEmptyExpr() {
cond.controls(result.getBasicBlock(), branch) and
cond.getCondition() = nonZeroGuard(length, branch) and
length.getField().hasName("length") and
length.getQualifier() = v.getAUse()
length.getQualifier() = v.getARead()
)
)
or
exists(SsaVariable v |
exists(SsaDefinition v |
// A use of a Collection variable is non-empty if...
result = v.getAUse() and
result = v.getARead() and
v.getSourceVariable().getType() instanceof CollectionType and
exists(ConditionBlock cond, boolean branch, Expr c |
// ...it is guarded by a condition...
Expand All @@ -216,13 +216,13 @@ private Expr nonEmptyExpr() {
// ...and the condition proves that it is non-empty, either by using the `isEmpty` method...
c.(MethodCall).getMethod().hasName("isEmpty") and
branch = false and
c.(MethodCall).getQualifier() = v.getAUse()
c.(MethodCall).getQualifier() = v.getARead()
or
// ...or a check on its `size`.
exists(MethodCall size |
c = nonZeroGuard(size, branch) and
size.getMethod().hasName("size") and
size.getQualifier() = v.getAUse()
size.getQualifier() = v.getARead()
)
)
)
Expand Down
4 changes: 2 additions & 2 deletions java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,10 @@ module Sem implements Semantic<Location> {

Type getSsaType(SsaVariable var) { result = var.getSourceVariable().getType() }

final private class FinalSsaVariable = SSA::SsaVariable;
final private class FinalSsaVariable = SSA::SsaDefinition;

class SsaVariable extends FinalSsaVariable {
Expr getAUse() { result = super.getAUse() }
Expr getAUse() { result = super.getARead() }
}

class SsaPhiNode extends SsaVariable instanceof SSA::SsaPhiDefinition {
Expand Down
4 changes: 2 additions & 2 deletions java/ql/lib/semmle/code/java/dataflow/RangeUtils.qll
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ ArrayCreationExpr getArrayDef(SsaVariable v) {
* `arrlen` without going through a back edge.
*/
private predicate arrayLengthDef(FieldRead arrlen, ArrayCreationExpr def) {
exists(SsaVariable arr |
exists(SsaDefinition arr |
arrlen.getField() instanceof ArrayLengthField and
arrlen.getQualifier() = arr.getAUse() and
arrlen.getQualifier() = arr.getARead() and
def = getArrayDef(arr)
)
}
Expand Down
4 changes: 2 additions & 2 deletions java/ql/lib/semmle/code/java/dataflow/SSA.qll
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,8 @@ private class RefTypeCastingExpr extends CastingExpr {
*
* The `VarAccess` represents the access to `v` that `result` has the same value as.
*/
Expr sameValue(SsaVariable v, VarAccess va) {
result = v.getAUse() and result = va
Expr sameValue(SsaDefinition v, VarAccess va) {
result = v.getARead() and result = va
or
result.(AssignExpr).getDest() = va and result = v.(SsaExplicitWrite).getDefiningExpr()
or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)
* updates.
*/
predicate hasNonlocalValue(FieldRead fr) {
not exists(SsaVariable v | v.getAUse() = fr)
not exists(SsaDefinition v | v.getARead() = fr)
or
exists(SsaDefinition v, SsaDefinition def |
v.getARead() = fr and def = v.getAnUltimateDefinition()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ private import java as J
private import semmle.code.java.dataflow.SSA as Ssa
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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ module Private {

class BasicBlock = BB::BasicBlock;

class SsaVariable = Ssa::SsaVariable;
class SsaVariable extends Ssa::SsaDefinition {
Expr getAUse() { result = super.getARead() }
}

class SsaPhiNode = Ssa::SsaPhiDefinition;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ private module Impl {
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() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ private import semmle.code.java.dataflow.SSA as Ssa
private import semmle.code.java.controlflow.BasicBlocks as BB
private import SsaReadPositionCommon

class SsaVariable = Ssa::SsaVariable;
class SsaVariable = Ssa::SsaDefinition;

class SsaPhiNode = Ssa::SsaPhiDefinition;

class BasicBlock = BB::BasicBlock;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ class RightShiftOp extends Expr {
}

private predicate boundedRead(VarRead read) {
exists(SsaVariable v, ConditionBlock cb, ComparisonExpr comp, boolean testIsTrue |
read = v.getAUse() and
exists(SsaDefinition v, ConditionBlock cb, ComparisonExpr comp, boolean testIsTrue |
read = v.getARead() and
cb.controls(read.getBasicBlock(), testIsTrue) and
cb.getCondition() = comp
|
comp.getLesserOperand() = v.getAUse() and testIsTrue = true
comp.getLesserOperand() = v.getARead() and testIsTrue = true
or
comp.getGreaterOperand() = v.getAUse() and testIsTrue = false
comp.getGreaterOperand() = v.getARead() and testIsTrue = false
)
}

Expand Down
6 changes: 3 additions & 3 deletions java/ql/lib/semmle/code/java/security/Validation.qll
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ private predicate validationCall(MethodCall ma, VarAccess va) {
}

private predicate validatedAccess(VarAccess va) {
exists(SsaVariable v, MethodCall guardcall |
va = v.getAUse() and
validationCall(guardcall, v.getAUse())
exists(SsaDefinition v, MethodCall guardcall |
va = v.getARead() and
validationCall(guardcall, v.getARead())
|
guardcall.(Guard).controls(va.getBasicBlock(), _)
or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import semmle.code.java.dataflow.RangeUtils
import semmle.code.java.dataflow.RangeAnalysis

pragma[nomagic]
predicate ssaArrayLengthBound(SsaVariable arr, Bound b) {
predicate ssaArrayLengthBound(SsaDefinition arr, Bound b) {
exists(FieldAccess len |
len.getField() instanceof ArrayLengthField and
len.getQualifier() = arr.getAUse() and
len.getQualifier() = arr.getARead() and
b.getExpr() = len
)
}
Expand All @@ -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`.
*/
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.getArray() = arr.getAUse() and
aa.getArray() = arr.getARead() and
bounded(index, b, delta, true, _)
|
ssaArrayLengthBound(arr, b) and
Expand Down
16 changes: 8 additions & 8 deletions java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,22 @@ Expr overFlowCand() {
predicate positiveOrNegative(Expr e) { positive(e) or negative(e) }

/** Gets an expression that equals `v` plus a positive or negative value. */
Expr increaseOrDecreaseOfVar(SsaVariable v) {
Expr increaseOrDecreaseOfVar(SsaDefinition v) {
exists(AssignAddExpr add |
result = add and
positiveOrNegative(add.getDest()) and
add.getRhs() = v.getAUse()
add.getRhs() = v.getARead()
)
or
exists(AddExpr add, Expr e |
result = add and
add.hasOperands(v.getAUse(), e) and
add.hasOperands(v.getARead(), e) and
positiveOrNegative(e)
)
or
exists(SubExpr sub |
result = sub and
sub.getLeftOperand() = v.getAUse() and
sub.getLeftOperand() = v.getARead() and
positiveOrNegative(sub.getRightOperand())
)
or
Expand All @@ -172,7 +172,7 @@ Expr increaseOrDecreaseOfVar(SsaVariable v) {

predicate overFlowTest(ComparisonExpr comp) {
(
exists(SsaVariable v | comp.hasOperands(increaseOrDecreaseOfVar(v), v.getAUse()))
exists(SsaDefinition v | comp.hasOperands(increaseOrDecreaseOfVar(v), v.getARead()))
or
comp.getLesserOperand() = overFlowCand() and
comp.getGreaterOperand().(IntegerLiteral).getIntValue() = 0
Expand All @@ -195,9 +195,9 @@ predicate concurrentModificationTest(BinaryExpr test) {
*/
pragma[nomagic]
predicate guardedTest(EqualityTest test, Guard guard, boolean isEq, int i1, int i2) {
exists(SsaVariable v, CompileTimeConstantExpr c1, CompileTimeConstantExpr c2 |
guard.isEquality(v.getAUse(), c1, isEq) and
test.hasOperands(v.getAUse(), c2) and
exists(SsaDefinition v, CompileTimeConstantExpr c1, CompileTimeConstantExpr c2 |
guard.isEquality(v.getARead(), c1, isEq) and
test.hasOperands(v.getARead(), c2) and
i1 = c1.getIntValue() and
i2 = c2.getIntValue() and
v.getSourceVariable().getType() instanceof IntegralType
Expand Down
14 changes: 7 additions & 7 deletions java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ class BoundKind extends string {
*/
predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
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
|
s1.getCondition() = cond and
cb.getCondition() = cond and
cond.hasOperands(v.getAUse(), c1) and
cond.hasOperands(v.getARead(), c1) and
c1.getIntValue() = k1 and
test.hasOperands(v.getAUse(), c2) and
test.hasOperands(v.getARead(), c2) and
c2.getIntValue() = k2 and
v.getSourceVariable().getVariable() instanceof LocalScopeVariable and
cb.controls(test.getBasicBlock(), condIsTrue) and
Expand All @@ -49,7 +49,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
)
or
exists(ComparisonExpr comp | comp = cond |
comp.getLesserOperand() = v.getAUse() and
comp.getLesserOperand() = v.getARead() and
(
condIsTrue = true and
boundKind.isUpper() and
Expand All @@ -60,7 +60,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
(if comp.isStrict() then bound = k1 else bound = k1 + 1)
)
or
comp.getGreaterOperand() = v.getAUse() and
comp.getGreaterOperand() = v.getARead() and
(
condIsTrue = true and
boundKind.isLower() and
Expand Down Expand Up @@ -88,7 +88,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
)
or
exists(ComparisonExpr comp | comp = test |
comp.getLesserOperand() = v.getAUse() and
comp.getLesserOperand() = v.getARead() and
(
boundKind.providesLowerBound() and
testIsTrue = false and
Expand All @@ -107,7 +107,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
)
)
or
comp.getGreaterOperand() = v.getAUse() and
comp.getGreaterOperand() = v.getARead() and
(
boundKind.providesLowerBound() and
testIsTrue = true and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ predicate requiresInstanceOf(Expr e, VarAccess va, RefType 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) {
exists(SsaVariable ssa |
exists(SsaDefinition ssa |
ssa.getSourceVariable().getVariable() = v and
requiresInstanceOf(e, ssa.getAUse(), t) and
requiresInstanceOf(e, ssa.getARead(), t) and
sup = t.getAnAncestor() and
instanceOfCheck(cond, ssa.getAUse(), sup) and
instanceOfCheck(cond, ssa.getARead(), sup) and
cond.(Guard).controls(e.getBasicBlock(), false) and
not t instanceof ErrorType and
not sup instanceof ErrorType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ where
loopWhileTrue(loop) and loopExitGuard(loop, cond)
) and
// None of the ssa variables in `cond` are updated inside the loop.
forex(SsaVariable ssa, VarRead use | ssa.getAUse() = use and use.getParent*() = cond |
not ssa.getCfgNode().getEnclosingStmt().getEnclosingStmt*() = loop or
ssa.getCfgNode().asExpr().getParent*() = loop.(ForStmt).getAnInit()
forex(SsaDefinition ssa, VarRead use | ssa.getARead() = use and use.getParent*() = cond |
not ssa.getControlFlowNode().getEnclosingStmt().getEnclosingStmt*() = loop or
ssa.getControlFlowNode().asExpr().getParent*() = loop.(ForStmt).getAnInit()
) and
// And `cond` does not use method calls, field reads, or array reads.
not exists(MethodCall ma | ma.getParent*() = cond) and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ class CheckSignaturesGuard extends Guard instanceof EqualityTest {
}

predicate signatureChecked(Expr safe) {
exists(CheckSignaturesGuard g, SsaVariable v |
v.getAUse() = g.getCheckedExpr() and
safe = v.getAUse() and
exists(CheckSignaturesGuard g, SsaDefinition v |
v.getARead() = g.getCheckedExpr() and
safe = v.getARead() and
g.controls(safe.getBasicBlock(), g.(EqualityTest).polarity())
)
}
Expand Down
4 changes: 2 additions & 2 deletions java/ql/test/library-tests/ssa-large/countssa.ql
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import semmle.code.java.dataflow.SSA

from int uses, int live
where
uses = strictcount(SsaVariable ssa, VarRead use | use = ssa.getAUse()) and
live = strictcount(SsaVariable ssa, BasicBlock b | ssa.isLiveAtEndOfBlock(b))
uses = strictcount(SsaDefinition ssa, VarRead use | use = ssa.getARead()) and
live = strictcount(SsaDefinition ssa, BasicBlock b | ssa.isLiveAtEndOfBlock(b))
select uses, live
Loading