Skip to content

Commit 18eaa85

Browse files
committed
Java: Replace SSA class wrappers with shared code.
1 parent 487b5d2 commit 18eaa85

35 files changed

+407
-283
lines changed

java/ql/lib/semmle/code/java/dataflow/DefUse.qll

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ predicate useUsePair(VarRead use1, VarRead use2) { adjacentUseUse+(use1, use2) }
3434
* Other paths may also exist, so the SSA variables in `def` and `use` can be different.
3535
*/
3636
predicate defUsePair(VariableUpdate def, VarRead use) {
37-
exists(SsaVariable v |
38-
v.getAUse() = use and v.getAnUltimateDefinition().(SsaExplicitUpdate).getDefiningExpr() = def
37+
exists(SsaDefinition v, SsaExplicitWrite write |
38+
v.getARead() = use and write.getDefiningExpr() = def
39+
|
40+
v.getAnUltimateDefinition() = write
41+
or
42+
v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = write
3943
)
4044
}
4145

@@ -46,7 +50,9 @@ predicate defUsePair(VariableUpdate def, VarRead use) {
4650
* Other paths may also exist, so the SSA variables can be different.
4751
*/
4852
predicate parameterDefUsePair(Parameter p, VarRead use) {
49-
exists(SsaVariable v |
50-
v.getAUse() = use and v.getAnUltimateDefinition().(SsaImplicitInit).isParameterDefinition(p)
53+
exists(SsaDefinition v, SsaParameterInit init | v.getARead() = use and init.getParameter() = p |
54+
v.getAnUltimateDefinition() = init
55+
or
56+
v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = init
5157
)
5258
}

java/ql/lib/semmle/code/java/dataflow/NullGuards.qll

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ Expr enumConstEquality(Expr e, boolean polarity, EnumConstant c) {
2626
}
2727

2828
/** Gets an instanceof expression of `v` with type `type` */
29-
InstanceOfExpr instanceofExpr(SsaVariable v, RefType type) {
29+
InstanceOfExpr instanceofExpr(SsaDefinition v, RefType type) {
3030
result.getCheckedType() = type and
31-
result.getExpr() = v.getAUse()
31+
result.getExpr() = v.getARead()
3232
}
3333

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

@@ -91,37 +91,37 @@ Expr clearlyNotNullExpr(Expr reason) {
9191
(reason = r1 or reason = r2)
9292
)
9393
or
94-
exists(SsaVariable v, boolean branch, VarRead rval, Guard guard |
94+
exists(SsaDefinition v, boolean branch, VarRead rval, Guard guard |
9595
guard = directNullGuard(v, branch, false) and
9696
guard.controls(rval.getBasicBlock(), branch) and
9797
reason = guard and
98-
rval = v.getAUse() and
98+
rval = v.getARead() and
9999
result = rval and
100100
not result = baseNotNullExpr()
101101
)
102102
or
103-
exists(SsaVariable v |
103+
exists(SsaDefinition v |
104104
clearlyNotNull(v, reason) and
105-
result = v.getAUse() and
105+
result = v.getARead() and
106106
not result = baseNotNullExpr()
107107
)
108108
}
109109

110110
/** Holds if `v` is an SSA variable that is provably not `null`. */
111-
predicate clearlyNotNull(SsaVariable v, Expr reason) {
111+
predicate clearlyNotNull(SsaDefinition v, Expr reason) {
112112
exists(Expr src |
113-
src = v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() and
113+
src = v.(SsaExplicitWrite).getValue() and
114114
src = clearlyNotNullExpr(reason)
115115
)
116116
or
117117
exists(CatchClause cc, LocalVariableDeclExpr decl |
118118
decl = cc.getVariable() and
119-
decl = v.(SsaExplicitUpdate).getDefiningExpr() and
119+
decl = v.(SsaExplicitWrite).getDefiningExpr() and
120120
reason = decl
121121
)
122122
or
123-
exists(SsaVariable captured |
124-
v.(SsaImplicitInit).captures(captured) and
123+
exists(SsaDefinition captured |
124+
v.(SsaCapturedDefinition).captures(captured) and
125125
clearlyNotNull(captured, reason)
126126
)
127127
or
@@ -136,7 +136,7 @@ predicate clearlyNotNull(SsaVariable v, Expr reason) {
136136
Expr clearlyNotNullExpr() { result = clearlyNotNullExpr(_) }
137137

138138
/** Holds if `v` is an SSA variable that is provably not `null`. */
139-
predicate clearlyNotNull(SsaVariable v) { clearlyNotNull(v, _) }
139+
predicate clearlyNotNull(SsaDefinition v) { clearlyNotNull(v, _) }
140140

141141
/**
142142
* 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) {
207207
* If `result` evaluates to `branch`, then `v` is guaranteed to be null if `isnull`
208208
* is true, and non-null if `isnull` is false.
209209
*/
210-
Expr directNullGuard(SsaVariable v, boolean branch, boolean isnull) {
210+
Expr directNullGuard(SsaDefinition v, boolean branch, boolean isnull) {
211211
result = basicNullGuard(sameValue(v, _), branch, isnull)
212212
}
213213

@@ -219,7 +219,7 @@ Expr directNullGuard(SsaVariable v, boolean branch, boolean isnull) {
219219
* If `result` evaluates to `branch`, then `v` is guaranteed to be null if `isnull`
220220
* is true, and non-null if `isnull` is false.
221221
*/
222-
deprecated Guard nullGuard(SsaVariable v, boolean branch, boolean isnull) {
222+
deprecated Guard nullGuard(SsaDefinition v, boolean branch, boolean isnull) {
223223
result = directNullGuard(v, branch, isnull)
224224
}
225225

@@ -228,7 +228,9 @@ deprecated Guard nullGuard(SsaVariable v, boolean branch, boolean isnull) {
228228
* from `bb1` to `bb2` implies that `v` is guaranteed to be null if `isnull` is
229229
* true, and non-null if `isnull` is false.
230230
*/
231-
predicate nullGuardControlsBranchEdge(SsaVariable v, boolean isnull, BasicBlock bb1, BasicBlock bb2) {
231+
predicate nullGuardControlsBranchEdge(
232+
SsaDefinition v, boolean isnull, BasicBlock bb1, BasicBlock bb2
233+
) {
232234
exists(GuardValue gv |
233235
Guards_v3::ssaControlsBranchEdge(v, bb1, bb2, gv) and
234236
gv.isNullness(isnull)
@@ -240,7 +242,7 @@ predicate nullGuardControlsBranchEdge(SsaVariable v, boolean isnull, BasicBlock
240242
* `bb` `v` is guaranteed to be null if `isnull` is true, and non-null if
241243
* `isnull` is false.
242244
*/
243-
predicate nullGuardControls(SsaVariable v, boolean isnull, BasicBlock bb) {
245+
predicate nullGuardControls(SsaDefinition v, boolean isnull, BasicBlock bb) {
244246
exists(GuardValue gv |
245247
Guards_v3::ssaControls(v, bb, gv) and
246248
gv.isNullness(isnull)
@@ -263,6 +265,6 @@ predicate guardSuggestsExprMaybeNull(Expr guard, Expr e) {
263265
/**
264266
* Holds if `guard` is a guard expression that suggests that `v` might be null.
265267
*/
266-
predicate guardSuggestsVarMaybeNull(Expr guard, SsaVariable v) {
268+
predicate guardSuggestsVarMaybeNull(Expr guard, SsaDefinition v) {
267269
guardSuggestsExprMaybeNull(guard, sameValue(v, _))
268270
}

java/ql/lib/semmle/code/java/dataflow/Nullness.qll

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,15 @@ predicate dereference(Expr e) {
113113
*
114114
* The `VarAccess` is included for nicer error reporting.
115115
*/
116-
private ControlFlowNode varDereference(SsaVariable v, VarAccess va) {
116+
private ControlFlowNode varDereference(SsaDefinition v, VarAccess va) {
117117
dereference(result.asExpr()) and
118118
result.asExpr() = sameValue(v, va)
119119
}
120120

121121
/**
122122
* The first dereference of a variable in a given `BasicBlock`.
123123
*/
124-
private predicate firstVarDereferenceInBlock(BasicBlock bb, SsaVariable v, VarAccess va) {
124+
private predicate firstVarDereferenceInBlock(BasicBlock bb, SsaDefinition v, VarAccess va) {
125125
exists(ControlFlowNode n |
126126
varDereference(v, va) = n and
127127
n.getBasicBlock() = bb and
@@ -135,14 +135,14 @@ private predicate firstVarDereferenceInBlock(BasicBlock bb, SsaVariable v, VarAc
135135
}
136136

137137
/** A variable suspected of being `null`. */
138-
private predicate varMaybeNull(SsaVariable v, ControlFlowNode node, string msg, Expr reason) {
138+
private predicate varMaybeNull(SsaDefinition v, ControlFlowNode node, string msg, Expr reason) {
139139
// A variable compared to null might be null.
140140
exists(Expr e |
141141
reason = e and
142142
msg = "as suggested by $@ null guard" and
143143
guardSuggestsVarMaybeNull(e, v) and
144-
node = v.getCfgNode() and
145-
not v instanceof SsaPhiNode and
144+
node = v.getControlFlowNode() and
145+
not v instanceof SsaPhiDefinition and
146146
not clearlyNotNull(v) and
147147
// Comparisons in finally blocks are excluded since missing exception edges in the CFG could otherwise yield FPs.
148148
not exists(TryStmt try | try.getFinally() = e.getEnclosingStmt().getEnclosingStmt*()) and
@@ -151,13 +151,13 @@ private predicate varMaybeNull(SsaVariable v, ControlFlowNode node, string msg,
151151
not exists(MethodCall ma | ma.getAnArgument().getAChildExpr*() = e)
152152
) and
153153
// Don't use a guard as reason if there is a null assignment.
154-
not v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = nullExpr()
154+
not v.(SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = nullExpr()
155155
)
156156
or
157157
// A parameter might be null if there is a null argument somewhere.
158158
exists(Parameter p, Expr arg |
159-
v.(SsaImplicitInit).isParameterDefinition(p) and
160-
node = v.getCfgNode() and
159+
v.(SsaParameterInit).getParameter() = p and
160+
node = v.getControlFlowNode() and
161161
p.getAnArgument() = arg and
162162
reason = arg and
163163
msg = "because of $@ null argument" and
@@ -167,7 +167,7 @@ private predicate varMaybeNull(SsaVariable v, ControlFlowNode node, string msg,
167167
or
168168
// If the source of a variable is null then the variable may be null.
169169
exists(VariableAssign def |
170-
v.(SsaExplicitUpdate).getDefiningExpr() = def and
170+
v.(SsaExplicitWrite).getDefiningExpr() = def and
171171
def.getSource() = nullExpr(node.asExpr()) and
172172
reason = def and
173173
msg = "because of $@ assignment"
@@ -179,26 +179,26 @@ private Expr nonEmptyExpr() {
179179
// An array creation with a known positive size is trivially non-empty.
180180
result.(ArrayCreationExpr).getFirstDimensionSize() > 0
181181
or
182-
exists(SsaVariable v |
182+
exists(SsaDefinition v |
183183
// A use of an array variable is non-empty if...
184-
result = v.getAUse() and
184+
result = v.getARead() and
185185
v.getSourceVariable().getType() instanceof Array
186186
|
187187
// ...its definition is non-empty...
188-
v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = nonEmptyExpr()
188+
v.(SsaExplicitWrite).getValue() = nonEmptyExpr()
189189
or
190190
// ...or it is guarded by a condition proving its length to be non-zero.
191191
exists(ConditionBlock cond, boolean branch, FieldAccess length |
192192
cond.controls(result.getBasicBlock(), branch) and
193193
cond.getCondition() = nonZeroGuard(length, branch) and
194194
length.getField().hasName("length") and
195-
length.getQualifier() = v.getAUse()
195+
length.getQualifier() = v.getARead()
196196
)
197197
)
198198
or
199-
exists(SsaVariable v |
199+
exists(SsaDefinition v |
200200
// A use of a Collection variable is non-empty if...
201-
result = v.getAUse() and
201+
result = v.getARead() and
202202
v.getSourceVariable().getType() instanceof CollectionType and
203203
exists(ConditionBlock cond, boolean branch, Expr c |
204204
// ...it is guarded by a condition...
@@ -216,13 +216,13 @@ private Expr nonEmptyExpr() {
216216
// ...and the condition proves that it is non-empty, either by using the `isEmpty` method...
217217
c.(MethodCall).getMethod().hasName("isEmpty") and
218218
branch = false and
219-
c.(MethodCall).getQualifier() = v.getAUse()
219+
c.(MethodCall).getQualifier() = v.getARead()
220220
or
221221
// ...or a check on its `size`.
222222
exists(MethodCall size |
223223
c = nonZeroGuard(size, branch) and
224224
size.getMethod().hasName("size") and
225-
size.getQualifier() = v.getAUse()
225+
size.getQualifier() = v.getARead()
226226
)
227227
)
228228
)
@@ -266,7 +266,7 @@ private module NullnessFlow = ControlFlowReachability::Flow<NullnessConfig>;
266266
* Holds if the dereference of `v` at `va` might be `null`.
267267
*/
268268
predicate nullDeref(SsaSourceVariable v, VarAccess va, string msg, Expr reason) {
269-
exists(SsaVariable origin, SsaVariable ssa, ControlFlowNode src, ControlFlowNode sink |
269+
exists(SsaDefinition origin, SsaDefinition ssa, ControlFlowNode src, ControlFlowNode sink |
270270
varMaybeNull(origin, src, msg, reason) and
271271
NullnessFlow::flow(src, origin, sink, ssa) and
272272
ssa.getSourceVariable() = v and
@@ -278,9 +278,9 @@ predicate nullDeref(SsaSourceVariable v, VarAccess va, string msg, Expr reason)
278278
* A dereference of a variable that is always `null`.
279279
*/
280280
predicate alwaysNullDeref(SsaSourceVariable v, VarAccess va) {
281-
exists(BasicBlock bb, SsaVariable ssa |
282-
forall(SsaVariable def | def = ssa.getAnUltimateDefinition() |
283-
def.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = alwaysNullExpr()
281+
exists(BasicBlock bb, SsaDefinition ssa |
282+
forall(SsaDefinition def | def = ssa.getAnUltimateDefinition() |
283+
def.(SsaExplicitWrite).getValue() = alwaysNullExpr()
284284
)
285285
or
286286
nullGuardControls(ssa, true, bb) and

java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,17 +242,17 @@ module Sem implements Semantic<Location> {
242242

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

245-
final private class FinalSsaVariable = SSA::SsaVariable;
245+
final private class FinalSsaVariable = SSA::SsaDefinition;
246246

247247
class SsaVariable extends FinalSsaVariable {
248-
Expr getAUse() { result = super.getAUse() }
248+
Expr getAUse() { result = super.getARead() }
249249
}
250250

251-
class SsaPhiNode extends SsaVariable instanceof SSA::SsaPhiNode {
251+
class SsaPhiNode extends SsaVariable instanceof SSA::SsaPhiDefinition {
252252
predicate hasInputFromBlock(SsaVariable inp, BasicBlock bb) { super.hasInputFromBlock(inp, bb) }
253253
}
254254

255-
class SsaExplicitUpdate extends SsaVariable instanceof SSA::SsaExplicitUpdate {
255+
class SsaExplicitUpdate extends SsaVariable instanceof SSA::SsaExplicitWrite {
256256
Expr getDefiningExpr() { result = super.getDefiningExpr() }
257257
}
258258

java/ql/lib/semmle/code/java/dataflow/RangeUtils.qll

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ predicate eqFlowCond = U::eqFlowCond/5;
3333
* `SsaPhiNode` in order for the reflexive case of `nonNullSsaFwdStep*(..)` to
3434
* have non-`SsaPhiNode` results.
3535
*/
36-
private predicate nonNullSsaFwdStep(SsaVariable v, SsaVariable phi) {
37-
exists(SsaExplicitUpdate vnull, SsaPhiNode phi0 | phi0 = phi |
38-
2 = strictcount(phi0.getAPhiInput()) and
39-
vnull = phi0.getAPhiInput() and
40-
v = phi0.getAPhiInput() and
36+
private predicate nonNullSsaFwdStep(SsaDefinition v, SsaDefinition phi) {
37+
exists(SsaExplicitWrite vnull, SsaPhiDefinition phi0 | phi0 = phi |
38+
2 = strictcount(phi0.getAnInput()) and
39+
vnull = phi0.getAnInput() and
40+
v = phi0.getAnInput() and
4141
not backEdge(phi0, v, _) and
4242
vnull != v and
43-
vnull.getDefiningExpr().(VariableAssign).getSource() instanceof NullLiteral
43+
vnull.getValue() instanceof NullLiteral
4444
)
4545
}
4646

@@ -56,13 +56,13 @@ private predicate nonNullDefStep(Expr e1, Expr e2) {
5656
* explicit `ArrayCreationExpr` definition and that the definition does not go
5757
* through a back edge.
5858
*/
59-
ArrayCreationExpr getArrayDef(SsaVariable v) {
59+
ArrayCreationExpr getArrayDef(SsaDefinition v) {
6060
exists(Expr src |
61-
v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = src and
61+
v.(SsaExplicitWrite).getValue() = src and
6262
nonNullDefStep*(result, src)
6363
)
6464
or
65-
exists(SsaVariable mid |
65+
exists(SsaDefinition mid |
6666
result = getArrayDef(mid) and
6767
nonNullSsaFwdStep(mid, v)
6868
)
@@ -74,9 +74,9 @@ ArrayCreationExpr getArrayDef(SsaVariable v) {
7474
* `arrlen` without going through a back edge.
7575
*/
7676
private predicate arrayLengthDef(FieldRead arrlen, ArrayCreationExpr def) {
77-
exists(SsaVariable arr |
77+
exists(SsaDefinition arr |
7878
arrlen.getField() instanceof ArrayLengthField and
79-
arrlen.getQualifier() = arr.getAUse() and
79+
arrlen.getQualifier() = arr.getARead() and
8080
def = getArrayDef(arr)
8181
)
8282
}
@@ -86,9 +86,9 @@ pragma[nomagic]
8686
private predicate constantIntegerExpr(Expr e, int val) {
8787
e.(CompileTimeConstantExpr).getIntValue() = val
8888
or
89-
exists(SsaExplicitUpdate v, Expr src |
90-
e = v.getAUse() and
91-
src = v.getDefiningExpr().(VariableAssign).getSource() and
89+
exists(SsaExplicitWrite v, Expr src |
90+
e = v.getARead() and
91+
src = v.getValue() and
9292
constantIntegerExpr(src, val)
9393
)
9494
or
@@ -112,9 +112,9 @@ pragma[nomagic]
112112
private predicate constantBooleanExpr(Expr e, boolean val) {
113113
e.(CompileTimeConstantExpr).getBooleanValue() = val
114114
or
115-
exists(SsaExplicitUpdate v, Expr src |
116-
e = v.getAUse() and
117-
src = v.getDefiningExpr().(VariableAssign).getSource() and
115+
exists(SsaExplicitWrite v, Expr src |
116+
e = v.getARead() and
117+
src = v.getValue() and
118118
constantBooleanExpr(src, val)
119119
)
120120
or
@@ -125,9 +125,9 @@ pragma[nomagic]
125125
private predicate constantStringExpr(Expr e, string val) {
126126
e.(CompileTimeConstantExpr).getStringValue() = val
127127
or
128-
exists(SsaExplicitUpdate v, Expr src |
129-
e = v.getAUse() and
130-
src = v.getDefiningExpr().(VariableAssign).getSource() and
128+
exists(SsaExplicitWrite v, Expr src |
129+
e = v.getARead() and
130+
src = v.getValue() and
131131
constantStringExpr(src, val)
132132
)
133133
}

0 commit comments

Comments
 (0)