Skip to content

Commit 5882526

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: add 'variableLockCheck' predicate
1 parent 96f61ac commit 5882526

File tree

2 files changed

+24
-42
lines changed

2 files changed

+24
-42
lines changed

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,26 @@ predicate failedLock(LockType t, BasicBlock lockblock, BasicBlock exblock) {
112112
predicate heldByCurrentThreadCheck(LockType t, BasicBlock checkblock, BasicBlock falsesucc) {
113113
exists(ConditionBlock conditionBlock |
114114
conditionBlock.getCondition() = t.getIsHeldByCurrentThreadAccess()
115-
or
116-
// Assume that a boolean variable condition check that controls an unlock call
117-
// is checking the lock state similar to `isHeldByCurrentThread`.
118-
conditionBlock.getCondition() = any(VarAccess v | v.getType() instanceof BooleanType) and
119-
conditionBlock.controls(t.getUnlockAccess().getBasicBlock(), true)
115+
|
116+
conditionBlock.getBasicBlock() = checkblock and
117+
conditionBlock.getTestSuccessor(false) = falsesucc
118+
)
119+
}
120+
121+
/**
122+
* A variable access in `checkblock` that has `falsesucc` as the false successor.
123+
*
124+
* The variable access must have an assigned value that is a lock access on `t`, and
125+
* the true successor of `checkblock` must contain an unlock access.
126+
*/
127+
predicate variableLockCheck(LockType t, BasicBlock checkblock, BasicBlock falsesucc) {
128+
exists(ConditionBlock conditionBlock, VarAccess v |
129+
v.getType() instanceof BooleanType and
130+
// Ensure that a lock access is assigned to the variable
131+
v.getVariable().getAnAssignedValue() = t.getLockAccess() and
132+
// Ensure that the `true` successor of the condition block contains an unlock access
133+
conditionBlock.getTestSuccessor(true) = t.getUnlockAccess().getBasicBlock() and
134+
conditionBlock.getCondition() = v
120135
|
121136
conditionBlock.getBasicBlock() = checkblock and
122137
conditionBlock.getTestSuccessor(false) = falsesucc
@@ -136,8 +151,9 @@ predicate blockIsLocked(LockType t, BasicBlock src, BasicBlock b, int locks) {
136151
// The number of net locks from the `src` block to the predecessor block `pred` is `predlocks`.
137152
blockIsLocked(t, src, pred, predlocks) and
138153
// The recursive call ensures that at least one lock is held, so do not consider the false
139-
// successor of the `isHeldByCurrentThread()` check.
154+
// successor of the `isHeldByCurrentThread()` check and of `variableLockCheck`.
140155
not heldByCurrentThreadCheck(t, pred, b) and
156+
not variableLockCheck(t, pred, b) and
141157
// Count a failed lock as an unlock so the net is zero.
142158
(if failedLock(t, pred, b) then failedlock = 1 else failedlock = 0) and
143159
(

java/ql/test/query-tests/UnreleasedLock/UnreleasedLock.java

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,7 @@ void good8() {
9696
}
9797
}
9898

99-
// * New testing
100-
101-
void good9() { // * PASSES
99+
void good9() {
102100
boolean locked = mylock.tryLock();
103101
if (!locked) { return; }
104102
try {
@@ -110,7 +108,7 @@ void good9() { // * PASSES
110108
}
111109
}
112110

113-
void good10() { // ! FAILS
111+
void good10() {
114112
boolean locked = false;
115113
try {
116114
locked = mylock.tryLock();
@@ -119,38 +117,6 @@ void good10() { // ! FAILS
119117
if (locked) {
120118
mylock.unlock();
121119
}
122-
// else { // * PASSES when add this
123-
// mylock.unlock();
124-
// }
125-
}
126-
}
127-
128-
void good11() { // * PASSES
129-
boolean locked = false;
130-
try {
131-
locked = mylock.tryLock();
132-
if (!locked) { return; }
133-
} finally {
134-
mylock.unlock();
135-
}
136-
}
137-
138-
void good12() { // * PASSES
139-
boolean locked = mylock.tryLock();
140-
if (locked){
141-
try {
142-
f();
143-
} finally {
144-
mylock.unlock();
145-
}
146-
}
147-
}
148-
149-
void good13() { // * PASSES
150-
try {
151-
mylock.lock();
152-
} finally {
153-
mylock.unlock();
154120
}
155121
}
156122
}

0 commit comments

Comments
 (0)