Skip to content

Commit 9b530e4

Browse files
committed
Java: IPA the CFG.
1 parent 1710f8d commit 9b530e4

38 files changed

+312
-208
lines changed

change-notes/1.20/analysis-java.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,15 @@
1717

1818
## Changes to QL libraries
1919

20+
* The class `ControlFlowNode` (and by extension `BasicBlock`) is no longer
21+
directly equatable to `Expr` and `Stmt`. Any queries that have been
22+
exploiting these equalities, for example by using casts, will need minor
23+
updates in order to fix any compilation errors. Conversions can be inserted
24+
in either direction depending on what is most convenient. Available
25+
conversions include `Expr.getControlFlowNode()`, `Stmt.getControlFlowNode()`,
26+
`ControlFlowNode.asExpr()`, `ControlFlowNode.asStmt()`, and
27+
`ControlFlowNode.asCall()`. Exit nodes were until now modelled as a
28+
`ControlFlowNode` equal to its enclosing `Callable`; these are now instead
29+
modelled by the class `ControlFlow::ExitNode`.
30+
2031

java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
3535
ConditionBlock cb, SsaVariable v, BinaryExpr cond, boolean condIsTrue, int k1, int k2,
3636
CompileTimeConstantExpr c1, CompileTimeConstantExpr c2
3737
|
38-
s1 = cond and
38+
s1.getCondition() = cond and
3939
cb.getCondition() = cond and
4040
cond.hasOperands(v.getAUse(), c1) and
4141
c1.getIntValue() = k1 and

java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingWithInitRace.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ where
3636
doubleCheckedLocking(if1, if2, sync, f) and
3737
a.getEnclosingStmt().getParent*() = if2.getThen() and
3838
se.getEnclosingStmt().getParent*() = sync.getBlock() and
39-
a.(ControlFlowNode).getASuccessor+() = se and
39+
a.getControlFlowNode().getASuccessor+() = se.getControlFlowNode() and
4040
a.getDest().(FieldAccess).getField() = f
4141
select a,
4242
"Potential race condition. This assignment to $@ is visible to other threads before the subsequent statements are executed.",

java/ql/src/Likely Bugs/Concurrency/LazyInitStaticField.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ class ValidSynchStmt extends Stmt {
6363
exists(MethodAccess lockAction |
6464
lockAction.getQualifier() = lockField.getAnAccess() and
6565
lockAction.getMethod().getName() = "lock" and
66-
dominates(lockAction, this)
66+
dominates(lockAction.getControlFlowNode(), this.getControlFlowNode())
6767
) and
6868
exists(MethodAccess unlockAction |
6969
unlockAction.getQualifier() = lockField.getAnAccess() and
7070
unlockAction.getMethod().getName() = "unlock" and
71-
postDominates(unlockAction, this)
71+
postDominates(unlockAction.getControlFlowNode(), this.getControlFlowNode())
7272
)
7373
)
7474
}

java/ql/src/Likely Bugs/Concurrency/UnreleasedLock.ql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ class LockType extends RefType {
5858
}
5959

6060
predicate lockBlock(LockType t, BasicBlock b, int locks) {
61-
locks = strictcount(int i | b.getNode(i) = t.getLockAccess())
61+
locks = strictcount(int i | b.getNode(i) = t.getLockAccess().getControlFlowNode())
6262
}
6363

6464
predicate unlockBlock(LockType t, BasicBlock b, int unlocks) {
65-
unlocks = strictcount(int i | b.getNode(i) = t.getUnlockAccess())
65+
unlocks = strictcount(int i | b.getNode(i) = t.getUnlockAccess().getControlFlowNode())
6666
}
6767

6868
/**
@@ -89,11 +89,11 @@ predicate failedLock(LockType t, BasicBlock lockblock, BasicBlock exblock) {
8989
exists(ControlFlowNode lock |
9090
lock = lockblock.getLastNode() and
9191
(
92-
lock = t.getLockAccess()
92+
lock = t.getLockAccess().getControlFlowNode()
9393
or
9494
exists(SsaExplicitUpdate lockbool |
9595
// Using the value of `t.getLockAccess()` ensures that it is a `tryLock` call.
96-
lock = lockbool.getAUse() and
96+
lock = lockbool.getAUse().getControlFlowNode() and
9797
lockbool.getDefiningExpr().(VariableAssign).getSource() = t.getLockAccess()
9898
)
9999
) and
@@ -151,7 +151,7 @@ where
151151
// Restrict results to those methods that actually attempt to unlock.
152152
t.getUnlockAccess().getEnclosingCallable() = c and
153153
blockIsLocked(t, src, exit, _) and
154-
exit.getLastNode() = c and
155-
lock = src.getANode() and
154+
exit.getLastNode().(ControlFlow::ExitNode).getEnclosingCallable() = c and
155+
lock.getControlFlowNode() = src.getANode() and
156156
lock = t.getLockAccess()
157157
select lock, "This lock might not be unlocked or might be locked more times than it is unlocked."

java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ predicate mainLoopCondition(LoopStmt loop, Expr cond) {
6161
else loopReentry = cond
6262
|
6363
last.getEnclosingStmt().getParent*() = loop.getBody() and
64-
last.getASuccessor().(Expr).getParent*() = loopReentry
64+
last.getASuccessor().asExpr().getParent*() = loopReentry
6565
)
6666
}
6767

@@ -75,7 +75,7 @@ where
7575
// None of the ssa variables in `cond` are updated inside the loop.
7676
forex(SsaVariable ssa, RValue use | ssa.getAUse() = use and use.getParent*() = cond |
7777
not ssa.getCFGNode().getEnclosingStmt().getParent*() = loop or
78-
ssa.getCFGNode().(Expr).getParent*() = loop.(ForStmt).getAnInit()
78+
ssa.getCFGNode().asExpr().getParent*() = loop.(ForStmt).getAnInit()
7979
) and
8080
// And `cond` does not use method calls, field reads, or array reads.
8181
not exists(MethodAccess ma | ma.getParent*() = cond) and

java/ql/src/Security/CWE/CWE-022/ZipSlip.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,14 @@ predicate validateFilePath(SsaVariable var, Guard check) {
130130
* Holds if `m` validates its `arg`th parameter.
131131
*/
132132
predicate validationMethod(Method m, int arg) {
133-
exists(Guard check, SsaImplicitInit var, ControlFlowNode exit, ControlFlowNode normexit |
133+
exists(Guard check, SsaImplicitInit var, ControlFlow::ExitNode exit, ControlFlowNode normexit |
134134
validateFilePath(var, check) and
135135
var.isParameterDefinition(m.getParameter(arg)) and
136-
exit = m and
136+
exit.getEnclosingCallable() = m and
137137
normexit.getANormalSuccessor() = exit and
138138
1 = strictcount(ControlFlowNode n | n.getANormalSuccessor() = exit)
139139
|
140-
check.(ConditionNode).getATrueSuccessor() = exit or
140+
check.hasBranchEdge(_, exit.getBasicBlock(), true) or
141141
check.controls(normexit.getBasicBlock(), true)
142142
)
143143
}

java/ql/src/Security/CWE/CWE-833/LockOrderInconsistency.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ predicate badReentrantLockOrder(MethodAccess first, MethodAccess second, MethodA
7777
otherSecond = v1.getLockAction() and
7878
second = v2.getLockAction() and
7979
otherFirst = v2.getLockAction() and
80-
first.(ControlFlowNode).getASuccessor+() = second and
81-
otherFirst.(ControlFlowNode).getASuccessor+() = otherSecond
80+
first.getControlFlowNode().getASuccessor+() = second.getControlFlowNode() and
81+
otherFirst.getControlFlowNode().getASuccessor+() = otherSecond.getControlFlowNode()
8282
|
8383
v1 != v2
8484
)

java/ql/src/Violations of Best Practice/Declarations/BreakInSwitchCase.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import Common
1717
from SwitchStmt s, Stmt c
1818
where
1919
c = s.getACase() and
20-
not c.(ControlFlowNode).getASuccessor() instanceof ConstCase and
21-
not c.(ControlFlowNode).getASuccessor() instanceof DefaultCase and
20+
not c.getControlFlowNode().getASuccessor().asStmt() instanceof ConstCase and
21+
not c.getControlFlowNode().getASuccessor().asStmt() instanceof DefaultCase and
2222
not s.(Annotatable).suppressesWarningsAbout("fallthrough") and
2323
mayDropThroughWithoutComment(s, c)
2424
select c,

java/ql/src/Violations of Best Practice/Declarations/Common.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ predicate switchCaseControlFlowPlus(SwitchStmt switch, BasicBlock b1, BasicBlock
2424
exists(BasicBlock mid |
2525
switchCaseControlFlowPlus(switch, mid, b2) and
2626
switchCaseControlFlow(switch, b1, mid) and
27-
not mid.getFirstNode() = switch.getACase()
27+
not mid.getFirstNode() = switch.getACase().getControlFlowNode()
2828
)
2929
}
3030

3131
predicate mayDropThroughWithoutComment(SwitchStmt switch, Stmt switchCase) {
3232
switchCase = switch.getACase() and
3333
exists(Stmt other, BasicBlock b1, BasicBlock b2 |
34-
b1.getFirstNode() = switchCase and
35-
b2.getFirstNode() = other and
34+
b1.getFirstNode() = switchCase.getControlFlowNode() and
35+
b2.getFirstNode() = other.getControlFlowNode() and
3636
switchCaseControlFlowPlus(switch, b1, b2) and
3737
other = switch.getACase() and
3838
not fallThroughCommented(other)

0 commit comments

Comments
 (0)