Skip to content

Commit 96f61ac

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: initial experimentation
1 parent 93b1114 commit 96f61ac

File tree

2 files changed

+72
-9
lines changed

2 files changed

+72
-9
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ 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)
115120
|
116121
conditionBlock.getBasicBlock() = checkblock and
117122
conditionBlock.getTestSuccessor(false) = falsesucc

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

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ void lock() throws RuntimeException { }
55
void unlock() { }
66
boolean isHeldByCurrentThread() { return true; }
77
}
8-
8+
99
void f() throws RuntimeException { }
1010
void g() throws RuntimeException { }
11-
11+
1212
MyLock mylock = new MyLock();
13-
13+
1414
void bad1() {
1515
mylock.lock();
1616
f();
1717
mylock.unlock();
1818
}
19-
19+
2020
void good2() {
2121
mylock.lock();
2222
try {
@@ -25,7 +25,7 @@ void good2() {
2525
mylock.unlock();
2626
}
2727
}
28-
28+
2929
void bad3() {
3030
mylock.lock();
3131
f();
@@ -35,7 +35,7 @@ void bad3() {
3535
mylock.unlock();
3636
}
3737
}
38-
38+
3939
void bad4() {
4040
mylock.lock();
4141
try {
@@ -45,7 +45,7 @@ void bad4() {
4545
mylock.unlock();
4646
}
4747
}
48-
48+
4949
void bad5(boolean lockmore) {
5050
mylock.lock();
5151
try {
@@ -58,7 +58,7 @@ void bad5(boolean lockmore) {
5858
mylock.unlock();
5959
}
6060
}
61-
61+
6262
void good6() {
6363
if (!mylock.tryLock()) { return; }
6464
try {
@@ -67,7 +67,7 @@ void good6() {
6767
mylock.unlock();
6868
}
6969
}
70-
70+
7171
void bad7() {
7272
if (!mylock.tryLock()) { return; }
7373
f();
@@ -95,4 +95,62 @@ void good8() {
9595
mylock.unlock();
9696
}
9797
}
98+
99+
// * New testing
100+
101+
void good9() { // * PASSES
102+
boolean locked = mylock.tryLock();
103+
if (!locked) { return; }
104+
try {
105+
f();
106+
} finally {
107+
if (locked) {
108+
mylock.unlock();
109+
}
110+
}
111+
}
112+
113+
void good10() { // ! FAILS
114+
boolean locked = false;
115+
try {
116+
locked = mylock.tryLock();
117+
if (!locked) { return; }
118+
} finally {
119+
if (locked) {
120+
mylock.unlock();
121+
}
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();
154+
}
155+
}
98156
}

0 commit comments

Comments
 (0)