Skip to content

Commit cf8d1bd

Browse files
committed
Java: Replace SSA class wrappers with shared code.
1 parent 8916315 commit cf8d1bd

37 files changed

+443
-329
lines changed

java/ql/lib/semmle/code/java/controlflow/ControlFlowReachability.qll

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ module;
66

77
import java
88
private import codeql.controlflow.ControlFlowReachability
9-
private import semmle.code.java.dataflow.SSA as SSA
9+
private import semmle.code.java.dataflow.SSA
1010
private import semmle.code.java.controlflow.Guards as Guards
1111

1212
private module ControlFlowInput implements InputSig<Location, ControlFlowNode, BasicBlock> {
1313
private import java as J
14+
import Ssa
1415

1516
AstNode getEnclosingAstNode(ControlFlowNode node) { node.getAstNode() = result }
1617

@@ -27,23 +28,6 @@ private module ControlFlowInput implements InputSig<Location, ControlFlowNode, B
2728

2829
class Expr = J::Expr;
2930

30-
class SourceVariable = SSA::SsaSourceVariable;
31-
32-
class SsaDefinition = SSA::SsaVariable;
33-
34-
class SsaExplicitWrite extends SsaDefinition instanceof SSA::SsaExplicitUpdate {
35-
Expr getValue() {
36-
super.getDefiningExpr().(VariableAssign).getSource() = result or
37-
super.getDefiningExpr().(AssignOp) = result
38-
}
39-
}
40-
41-
class SsaPhiDefinition = SSA::SsaPhiNode;
42-
43-
class SsaUncertainWrite extends SsaDefinition instanceof SSA::SsaUncertainImplicitUpdate {
44-
SsaDefinition getPriorDefinition() { result = super.getPriorDef() }
45-
}
46-
4731
class GuardValue = Guards::GuardValue;
4832

4933
predicate ssaControlsBranchEdge(SsaDefinition def, BasicBlock bb1, BasicBlock bb2, GuardValue v) {

java/ql/lib/semmle/code/java/controlflow/Guards.qll

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -416,30 +416,8 @@ private module LogicInput_v1 implements GuardsImpl::LogicInputSig {
416416
}
417417

418418
private module LogicInput_v2 implements GuardsImpl::LogicInputSig {
419-
private import semmle.code.java.dataflow.SSA as SSA
420-
421-
final private class FinalSsaVariable = SSA::SsaVariable;
422-
423-
class SsaDefinition extends FinalSsaVariable {
424-
GuardsInput::Expr getARead() { result = this.getAUse() }
425-
}
426-
427-
class SsaExplicitWrite extends SsaDefinition instanceof SSA::SsaExplicitUpdate {
428-
GuardsInput::Expr getValue() {
429-
super.getDefiningExpr().(VariableAssign).getSource() = result or
430-
super.getDefiningExpr().(AssignOp) = result
431-
}
432-
}
433-
434-
class SsaPhiDefinition extends SsaDefinition instanceof SSA::SsaPhiNode {
435-
predicate hasInputFromBlock(SsaDefinition inp, BasicBlock bb) {
436-
super.hasInputFromBlock(inp, bb)
437-
}
438-
}
439-
440-
class SsaParameterInit extends SsaDefinition instanceof SSA::SsaImplicitInit {
441-
Parameter getParameter() { super.isParameterDefinition(result) }
442-
}
419+
private import semmle.code.java.dataflow.SSA
420+
import Ssa
443421

444422
predicate additionalNullCheck = LogicInputCommon::additionalNullCheck/4;
445423

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: 23 additions & 23 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
)
@@ -249,9 +249,9 @@ private predicate impossibleEdge(BasicBlock bb1, BasicBlock bb2) {
249249
}
250250

251251
private module NullnessConfig implements ControlFlowReachability::ConfigSig {
252-
predicate source(ControlFlowNode node, SsaVariable def) { varMaybeNull(def, node, _, _) }
252+
predicate source(ControlFlowNode node, SsaDefinition def) { varMaybeNull(def, node, _, _) }
253253

254-
predicate sink(ControlFlowNode node, SsaVariable def) { varDereference(def, _) = node }
254+
predicate sink(ControlFlowNode node, SsaDefinition def) { varDereference(def, _) = node }
255255

256256
predicate barrierValue(GuardValue gv) { gv.isNullness(false) }
257257

@@ -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

0 commit comments

Comments
 (0)