mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
Merge pull request #19539 from yoff/java/conflicting-access
This commit is contained in:
3
java/ql/test/query-tests/Escaping/Escaping.expected
Normal file
3
java/ql/test/query-tests/Escaping/Escaping.expected
Normal file
@@ -0,0 +1,3 @@
|
||||
| Escaping.java:3:7:3:7 | x | The class $@ is marked as thread-safe, but this field is potentially escaping. | Escaping.java:2:14:2:21 | Escaping | Escaping |
|
||||
| Escaping.java:4:14:4:14 | y | The class $@ is marked as thread-safe, but this field is potentially escaping. | Escaping.java:2:14:2:21 | Escaping | Escaping |
|
||||
| Escaping.java:9:18:9:18 | b | The class $@ is marked as thread-safe, but this field is potentially escaping. | Escaping.java:2:14:2:21 | Escaping | Escaping |
|
||||
17
java/ql/test/query-tests/Escaping/Escaping.java
Normal file
17
java/ql/test/query-tests/Escaping/Escaping.java
Normal file
@@ -0,0 +1,17 @@
|
||||
@ThreadSafe
|
||||
public class Escaping {
|
||||
int x; //$ Alert
|
||||
public int y = 0; //$ Alert
|
||||
private int z = 3;
|
||||
final int w = 0;
|
||||
public final int u = 4;
|
||||
private final long a = 5;
|
||||
protected long b = 0; //$ Alert
|
||||
protected final long c = 0L;
|
||||
volatile long d = 3;
|
||||
protected volatile long e = 3L;
|
||||
|
||||
public void methodLocal() {
|
||||
int i;
|
||||
}
|
||||
}
|
||||
2
java/ql/test/query-tests/Escaping/Escaping.qlref
Normal file
2
java/ql/test/query-tests/Escaping/Escaping.qlref
Normal file
@@ -0,0 +1,2 @@
|
||||
query: Likely Bugs/Concurrency/Escaping.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
2
java/ql/test/query-tests/Escaping/ThreadSafe.java
Normal file
2
java/ql/test/query-tests/Escaping/ThreadSafe.java
Normal file
@@ -0,0 +1,2 @@
|
||||
public @interface ThreadSafe {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
| SafePublication.java:5:9:5:9 | z | The class $@ is marked as thread-safe, but this field is not safely published. | SafePublication.java:2:14:2:28 | SafePublication | SafePublication |
|
||||
| SafePublication.java:6:9:6:9 | w | The class $@ is marked as thread-safe, but this field is not safely published. | SafePublication.java:2:14:2:28 | SafePublication | SafePublication |
|
||||
| SafePublication.java:7:9:7:9 | u | The class $@ is marked as thread-safe, but this field is not safely published. | SafePublication.java:2:14:2:28 | SafePublication | SafePublication |
|
||||
| SafePublication.java:11:10:11:10 | d | The class $@ is marked as thread-safe, but this field is not safely published. | SafePublication.java:2:14:2:28 | SafePublication | SafePublication |
|
||||
| SafePublication.java:12:10:12:10 | e | The class $@ is marked as thread-safe, but this field is not safely published. | SafePublication.java:2:14:2:28 | SafePublication | SafePublication |
|
||||
| SafePublication.java:14:11:14:13 | arr | The class $@ is marked as thread-safe, but this field is not safely published. | SafePublication.java:2:14:2:28 | SafePublication | SafePublication |
|
||||
| SafePublication.java:17:10:17:11 | cc | The class $@ is marked as thread-safe, but this field is not safely published. | SafePublication.java:2:14:2:28 | SafePublication | SafePublication |
|
||||
@@ -0,0 +1,29 @@
|
||||
@ThreadSafe
|
||||
public class SafePublication {
|
||||
int x;
|
||||
int y = 0;
|
||||
int z = 3; //$ Alert
|
||||
int w; //$ Alert
|
||||
int u; //$ Alert
|
||||
long a;
|
||||
long b = 0;
|
||||
long c = 0L;
|
||||
long d = 3; //$ Alert
|
||||
long e = 3L; //$ Alert
|
||||
|
||||
int[] arr = new int[3]; //$ Alert
|
||||
float f = 0.0f;
|
||||
double dd = 00.0d;
|
||||
char cc = 'a'; //$ Alert
|
||||
char ok = '\u0000';
|
||||
|
||||
public SafePublication(int a) {
|
||||
x = 0;
|
||||
w = 3; // not ok
|
||||
u = a; // not ok
|
||||
}
|
||||
|
||||
public void methodLocal() {
|
||||
int i;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
query: Likely Bugs/Concurrency/SafePublication.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
2
java/ql/test/query-tests/SafePublication/ThreadSafe.java
Normal file
2
java/ql/test/query-tests/SafePublication/ThreadSafe.java
Normal file
@@ -0,0 +1,2 @@
|
||||
public @interface ThreadSafe {
|
||||
}
|
||||
45
java/ql/test/query-tests/ThreadSafe/ThreadSafe.expected
Normal file
45
java/ql/test/query-tests/ThreadSafe/ThreadSafe.expected
Normal file
@@ -0,0 +1,45 @@
|
||||
| examples/C.java:14:9:14:14 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:14:9:14:14 | this.y | this expression |
|
||||
| examples/C.java:15:9:15:14 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:15:9:15:14 | this.y | this expression |
|
||||
| examples/C.java:16:9:16:14 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:16:9:16:14 | this.y | this expression |
|
||||
| examples/C.java:16:18:16:23 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:16:18:16:23 | this.y | this expression |
|
||||
| examples/C.java:20:9:20:14 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:20:9:20:14 | this.y | this expression |
|
||||
| examples/C.java:21:9:21:14 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:21:9:21:14 | this.y | this expression |
|
||||
| examples/C.java:22:9:22:14 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:22:9:22:14 | this.y | this expression |
|
||||
| examples/C.java:22:18:22:23 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:22:18:22:23 | this.y | this expression |
|
||||
| examples/C.java:26:9:26:14 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:26:9:26:14 | this.y | this expression |
|
||||
| examples/C.java:30:13:30:13 | y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:30:13:30:13 | y | this expression |
|
||||
| examples/C.java:33:9:33:9 | y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/C.java:33:9:33:9 | y | this expression |
|
||||
| examples/DeepPaths.java:8:17:8:17 | y | This field is not properly synchronized in that no single monitor covers all accesses, but the class $@ is annotated as @ThreadSafe. | examples/DeepPaths.java:7:14:7:22 | DeepPaths | DeepPaths |
|
||||
| examples/FaultyTurnstileExample.java:18:5:18:9 | count | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/FaultyTurnstileExample.java:18:5:18:9 | count | this expression |
|
||||
| examples/FaultyTurnstileExample.java:26:15:26:19 | count | This field is not properly synchronized in that no single monitor covers all accesses, but the class $@ is annotated as @ThreadSafe. | examples/FaultyTurnstileExample.java:23:7:23:29 | FaultyTurnstileExample2 | FaultyTurnstileExample2 |
|
||||
| examples/FlawedSemaphore.java:15:14:15:18 | state | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/FlawedSemaphore.java:15:14:15:18 | state | this expression |
|
||||
| examples/FlawedSemaphore.java:18:7:18:11 | state | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/FlawedSemaphore.java:18:7:18:11 | state | this expression |
|
||||
| examples/LockExample.java:18:15:18:20 | length | This field is not properly synchronized in that no single monitor covers all accesses, but the class $@ is annotated as @ThreadSafe. | examples/LockExample.java:14:14:14:24 | LockExample | LockExample |
|
||||
| examples/LockExample.java:19:15:19:31 | notRelatedToOther | This field is not properly synchronized in that no single monitor covers all accesses, but the class $@ is annotated as @ThreadSafe. | examples/LockExample.java:14:14:14:24 | LockExample | LockExample |
|
||||
| examples/LockExample.java:20:17:20:23 | content | This field is not properly synchronized in that no single monitor covers all accesses, but the class $@ is annotated as @ThreadSafe. | examples/LockExample.java:14:14:14:24 | LockExample | LockExample |
|
||||
| examples/LockExample.java:44:5:44:10 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:44:5:44:10 | length | this expression |
|
||||
| examples/LockExample.java:45:5:45:11 | content | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:45:5:45:11 | content | this expression |
|
||||
| examples/LockExample.java:45:13:45:18 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:45:13:45:18 | length | this expression |
|
||||
| examples/LockExample.java:49:5:49:10 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:49:5:49:10 | length | this expression |
|
||||
| examples/LockExample.java:62:5:62:10 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:62:5:62:10 | length | this expression |
|
||||
| examples/LockExample.java:65:5:65:11 | content | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:65:5:65:11 | content | this expression |
|
||||
| examples/LockExample.java:65:13:65:18 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:65:13:65:18 | length | this expression |
|
||||
| examples/LockExample.java:69:5:69:10 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:69:5:69:10 | length | this expression |
|
||||
| examples/LockExample.java:71:5:71:11 | content | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:71:5:71:11 | content | this expression |
|
||||
| examples/LockExample.java:71:13:71:18 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:71:13:71:18 | length | this expression |
|
||||
| examples/LockExample.java:76:5:76:10 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:76:5:76:10 | length | this expression |
|
||||
| examples/LockExample.java:79:5:79:11 | content | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:79:5:79:11 | content | this expression |
|
||||
| examples/LockExample.java:79:13:79:18 | length | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:79:13:79:18 | length | this expression |
|
||||
| examples/LockExample.java:112:5:112:21 | notRelatedToOther | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:112:5:112:21 | notRelatedToOther | this expression |
|
||||
| examples/LockExample.java:119:5:119:21 | notRelatedToOther | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:119:5:119:21 | notRelatedToOther | this expression |
|
||||
| examples/LockExample.java:124:5:124:21 | notRelatedToOther | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:124:5:124:21 | notRelatedToOther | this expression |
|
||||
| examples/LockExample.java:145:5:145:21 | notRelatedToOther | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:145:5:145:21 | notRelatedToOther | this expression |
|
||||
| examples/LockExample.java:153:5:153:21 | notRelatedToOther | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/LockExample.java:153:5:153:21 | notRelatedToOther | this expression |
|
||||
| examples/ManyLocks.java:8:17:8:17 | y | This field is not properly synchronized in that no single monitor covers all accesses, but the class $@ is annotated as @ThreadSafe. | examples/ManyLocks.java:7:14:7:22 | ManyLocks | ManyLocks |
|
||||
| examples/SyncLstExample.java:45:5:45:7 | lst | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/SyncLstExample.java:45:5:45:7 | lst | this expression |
|
||||
| examples/SyncStackExample.java:37:5:37:7 | stc | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/SyncStackExample.java:37:5:37:7 | stc | this expression |
|
||||
| examples/SynchronizedAndLock.java:10:17:10:22 | length | This field is not properly synchronized in that no single monitor covers all accesses, but the class $@ is annotated as @ThreadSafe. | examples/SynchronizedAndLock.java:7:14:7:32 | SynchronizedAndLock | SynchronizedAndLock |
|
||||
| examples/Test.java:52:5:52:10 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/Test.java:24:5:24:18 | setYPrivate(...) | this expression |
|
||||
| examples/Test.java:60:5:60:10 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/Test.java:60:5:60:10 | this.y | this expression |
|
||||
| examples/Test.java:74:5:74:10 | this.y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/Test.java:74:5:74:10 | this.y | this expression |
|
||||
| examples/Test.java:74:14:74:14 | y | This field access (publicly accessible via $@) is not protected by any monitor, but the class is annotated as @ThreadSafe. | examples/Test.java:74:14:74:14 | y | this expression |
|
||||
2
java/ql/test/query-tests/ThreadSafe/ThreadSafe.qlref
Normal file
2
java/ql/test/query-tests/ThreadSafe/ThreadSafe.qlref
Normal file
@@ -0,0 +1,2 @@
|
||||
query: Likely Bugs/Concurrency/ThreadSafe.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
21
java/ql/test/query-tests/ThreadSafe/examples/Alias.java
Normal file
21
java/ql/test/query-tests/ThreadSafe/examples/Alias.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class Alias {
|
||||
private int y;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public void notMismatch() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
y = 42;
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
14
java/ql/test/query-tests/ThreadSafe/examples/App.java
Normal file
14
java/ql/test/query-tests/ThreadSafe/examples/App.java
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This Java source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package examples;
|
||||
|
||||
public class App {
|
||||
public String getGreeting() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(new App().getGreeting());
|
||||
}
|
||||
}
|
||||
72
java/ql/test/query-tests/ThreadSafe/examples/C.java
Normal file
72
java/ql/test/query-tests/ThreadSafe/examples/C.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class C {
|
||||
|
||||
private int y;
|
||||
private Lock lock = new ReentrantLock();
|
||||
private Lock lock2 = new ReentrantLock();
|
||||
|
||||
public void m() {
|
||||
this.y = 0; // $ Alert
|
||||
this.y += 1; // $ Alert
|
||||
this.y = this.y - 1; // $ Alert
|
||||
}
|
||||
|
||||
public void n4() {
|
||||
this.y = 0; // $ Alert
|
||||
this.y += 1; // $ Alert
|
||||
this.y = this.y - 1; // $ Alert
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y; // $ Alert
|
||||
}
|
||||
|
||||
public void test() {
|
||||
if (y == 0) { // $ Alert
|
||||
lock.lock();
|
||||
}
|
||||
y = 0; // $ Alert
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void n() {
|
||||
this.lock.lock();
|
||||
this.y = 0;
|
||||
this.y += 1;
|
||||
this.y = this.y - 1;
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
public void callTestLock2() {
|
||||
lock2.lock();
|
||||
setY(1);
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
public void n2() {
|
||||
lock.lock();
|
||||
this.y = 0;
|
||||
this.y += 1;
|
||||
this.y = this.y - 1;
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void n3() {
|
||||
lock.lock();
|
||||
y = 0;
|
||||
y += 1;
|
||||
y = y - 1;
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void callTest() {
|
||||
lock.lock();
|
||||
setY(1);
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
61
java/ql/test/query-tests/ThreadSafe/examples/DeepPaths.java
Normal file
61
java/ql/test/query-tests/ThreadSafe/examples/DeepPaths.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class DeepPaths {
|
||||
private int y; // $ Alert
|
||||
|
||||
private final Lock lock1 = new ReentrantLock();
|
||||
private final Lock lock2 = new ReentrantLock();
|
||||
private final Lock lock3 = new ReentrantLock();
|
||||
|
||||
public void layer1Locked() {
|
||||
lock1.lock();
|
||||
this.layer2Locked();
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
private void layer2Locked() {
|
||||
lock2.lock();
|
||||
this.layer3Unlocked();
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
private void layer3Locked() {
|
||||
lock3.lock();
|
||||
y++;
|
||||
lock3.unlock();
|
||||
}
|
||||
|
||||
public void layer1Skip() {
|
||||
lock2.lock();
|
||||
this.layer3Locked();
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
public void layer1Indirect() {
|
||||
this.layer2();
|
||||
}
|
||||
|
||||
private void layer2() {
|
||||
this.layer2Locked();
|
||||
}
|
||||
|
||||
public void layer1Unlocked() {
|
||||
this.layer2Unlocked();
|
||||
}
|
||||
|
||||
private void layer2Unlocked() {
|
||||
this.layer3();
|
||||
}
|
||||
|
||||
private void layer3() {
|
||||
this.layer3Locked();
|
||||
}
|
||||
|
||||
private void layer3Unlocked() {
|
||||
y++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
class FaultyTurnstileExample {
|
||||
private Lock lock = new ReentrantLock();
|
||||
private int count = 0;
|
||||
|
||||
public void inc() {
|
||||
lock.lock();
|
||||
count++; // $ MISSING: Alert
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void dec() {
|
||||
count--; // $ Alert
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
class FaultyTurnstileExample2 {
|
||||
private Lock lock1 = new ReentrantLock();
|
||||
private Lock lock2 = new ReentrantLock();
|
||||
private int count = 0; // $ Alert
|
||||
|
||||
public void inc() {
|
||||
lock1.lock();
|
||||
count++;
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void dec() {
|
||||
lock2.lock();
|
||||
count--;
|
||||
lock2.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package examples;
|
||||
|
||||
@ThreadSafe
|
||||
public class FlawedSemaphore {
|
||||
private final int capacity;
|
||||
private int state;
|
||||
|
||||
public FlawedSemaphore(int c) {
|
||||
capacity = c;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
public void acquire() {
|
||||
try {
|
||||
while (state == capacity) { // $ Alert
|
||||
this.wait();
|
||||
}
|
||||
state++; // $ Alert
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
synchronized (this) {
|
||||
state--; // State can become negative
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class LockCorrect {
|
||||
private Lock lock1 = new ReentrantLock();
|
||||
|
||||
private int length = 0;
|
||||
private int notRelatedToOther = 10;
|
||||
private int[] content = new int[10];
|
||||
private int thisSynchronized = 0;
|
||||
|
||||
public void add(int value) {
|
||||
lock1.lock();
|
||||
length++;
|
||||
content[length] = value;
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void removeCorrect() {
|
||||
lock1.lock();
|
||||
content[length] = 0;
|
||||
length--;
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void synchronizedOnLock1() {
|
||||
synchronized(lock1) {
|
||||
notRelatedToOther++;
|
||||
}
|
||||
}
|
||||
|
||||
public void synchronizedOnLock12() {
|
||||
synchronized(lock1) {
|
||||
notRelatedToOther++;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void x() {
|
||||
thisSynchronized++;
|
||||
}
|
||||
|
||||
public void x1() {
|
||||
synchronized(this) {
|
||||
thisSynchronized++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
156
java/ql/test/query-tests/ThreadSafe/examples/LockExample.java
Normal file
156
java/ql/test/query-tests/ThreadSafe/examples/LockExample.java
Normal file
@@ -0,0 +1,156 @@
|
||||
// This example shows that we only get one alert "per concurrency problem":
|
||||
// For each problematic variable, we get one alert at the earliest conflicting write.
|
||||
// If the variable is involved in several different monitors, we get an alert for each monitor that
|
||||
// is not correctly used.
|
||||
// A single alert can have many related locations, since each conflicting access which is not
|
||||
// properly synchronized is a related location.
|
||||
// This leads to many lines in the .expected file.
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class LockExample {
|
||||
private Lock lock1 = new ReentrantLock();
|
||||
private Lock lock2 = new ReentrantLock();
|
||||
|
||||
private int length = 0; // $ Alert
|
||||
private int notRelatedToOther = 10; // $ Alert
|
||||
private int[] content = new int[10]; // $ Alert
|
||||
|
||||
public void add(int value) {
|
||||
lock1.lock();
|
||||
length++;
|
||||
content[length] = value;
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void removeCorrect() {
|
||||
lock1.lock();
|
||||
length--;
|
||||
content[length] = 0;
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void notTheSameLockAsAdd() { // use locks, but different ones
|
||||
lock2.lock();
|
||||
length--;
|
||||
content[length] = 0;
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
public void noLock() { // no locks
|
||||
length--; // $ Alert
|
||||
content[length] = 0; // $ Alert
|
||||
}
|
||||
|
||||
public void fieldUpdatedOutsideOfLock() { // adjusts length without lock
|
||||
length--; // $ Alert
|
||||
|
||||
lock1.lock();
|
||||
content[length] = 0;
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public synchronized void synchronizedLock() { // no locks, but with synchronized
|
||||
length--;
|
||||
content[length] = 0;
|
||||
}
|
||||
|
||||
public void onlyLocked() { // never unlocked, only locked
|
||||
length--; // $ Alert
|
||||
|
||||
lock1.lock();
|
||||
content[length] = 0; // $ Alert
|
||||
}
|
||||
|
||||
public void onlyUnlocked() { // never locked, only unlocked
|
||||
length--; // $ Alert
|
||||
|
||||
content[length] = 0; // $ Alert
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void notSameLock() {
|
||||
length--; // $ Alert
|
||||
|
||||
lock2.lock();// Not the same lock
|
||||
content[length] = 0; // $ Alert
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void updateCount() {
|
||||
lock2.lock();
|
||||
notRelatedToOther++;
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
public void updateCountTwiceCorrect() {
|
||||
lock2.lock();
|
||||
notRelatedToOther++;
|
||||
lock2.unlock();
|
||||
lock1.lock();
|
||||
notRelatedToOther++;
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void updateCountTwiceDifferentLocks() {
|
||||
lock2.lock();
|
||||
notRelatedToOther++;
|
||||
lock2.unlock();
|
||||
lock1.lock();
|
||||
notRelatedToOther++;
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
public void updateCountTwiceLock() {
|
||||
lock2.lock();
|
||||
notRelatedToOther++;
|
||||
lock2.unlock();
|
||||
lock1.lock();
|
||||
notRelatedToOther++; // $ Alert
|
||||
}
|
||||
|
||||
public void updateCountTwiceUnLock() {
|
||||
lock2.lock();
|
||||
notRelatedToOther++;
|
||||
lock2.unlock();
|
||||
notRelatedToOther++; // $ Alert
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void synchronizedNonRelatedOutside() {
|
||||
notRelatedToOther++; // $ Alert
|
||||
|
||||
synchronized(this) {
|
||||
length++;
|
||||
}
|
||||
}
|
||||
|
||||
public void synchronizedNonRelatedOutside2() {
|
||||
int x = 0;
|
||||
x++;
|
||||
|
||||
synchronized(this) {
|
||||
length++;
|
||||
}
|
||||
}
|
||||
|
||||
public void synchronizedNonRelatedOutside3() {
|
||||
synchronized(this) {
|
||||
length++;
|
||||
}
|
||||
|
||||
notRelatedToOther = 1; // $ Alert
|
||||
}
|
||||
|
||||
public void synchronizedNonRelatedOutside4() {
|
||||
synchronized(lock1) {
|
||||
length++;
|
||||
}
|
||||
|
||||
notRelatedToOther = 1; // $ Alert
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package examples;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class LoopyCallGraph {
|
||||
private Lock lock = new ReentrantLock();
|
||||
private int count = 0;
|
||||
private Random random = new Random();
|
||||
|
||||
public void entry() {
|
||||
if (random.nextBoolean()) {
|
||||
increase(); // this could look like an unprotected path to a call to dec()
|
||||
} else {
|
||||
lock.lock();
|
||||
dec();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void increase() {
|
||||
lock.lock();
|
||||
count = 10;
|
||||
lock.unlock();
|
||||
entry(); // this could look like an unprotected path to a call to dec()
|
||||
}
|
||||
|
||||
private void dec() {
|
||||
count--;
|
||||
}
|
||||
}
|
||||
37
java/ql/test/query-tests/ThreadSafe/examples/ManyLocks.java
Normal file
37
java/ql/test/query-tests/ThreadSafe/examples/ManyLocks.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class ManyLocks {
|
||||
private int y; // $ Alert
|
||||
|
||||
private final Lock lock1 = new ReentrantLock();
|
||||
private final Lock lock2 = new ReentrantLock();
|
||||
private final Lock lock3 = new ReentrantLock();
|
||||
|
||||
public void inc() {
|
||||
lock1.lock();
|
||||
lock2.lock();
|
||||
y++;
|
||||
lock2.unlock();
|
||||
lock1.unlock();
|
||||
}
|
||||
|
||||
public void dec() {
|
||||
lock2.lock();
|
||||
lock3.lock();
|
||||
y--;
|
||||
lock3.unlock();
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
lock1.lock();
|
||||
lock3.lock();
|
||||
y = 0;
|
||||
lock3.unlock();
|
||||
lock1.unlock();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package examples;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class SyncLstExample<T> {
|
||||
private Lock lock = new ReentrantLock();
|
||||
private List<T> lst;
|
||||
|
||||
public SyncLstExample(List<T> lst) {
|
||||
this.lst = lst;
|
||||
}
|
||||
|
||||
public void add(T item) {
|
||||
lock.lock();
|
||||
lst.add(item);
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void remove(int i) {
|
||||
lock.lock();
|
||||
lst.remove(i);
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
class FaultySyncLstExample<T> {
|
||||
private Lock lock = new ReentrantLock();
|
||||
private List<T> lst;
|
||||
|
||||
public FaultySyncLstExample(List<T> lst) {
|
||||
this.lst = lst;
|
||||
}
|
||||
|
||||
public void add(T item) {
|
||||
lock.lock();
|
||||
lst.add(item);
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void remove(int i) {
|
||||
lst.remove(i); // $ Alert
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package examples;
|
||||
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class SyncStackExample<T> {
|
||||
private Lock lock = new ReentrantLock();
|
||||
private Stack<T> stc = new Stack<T>();
|
||||
|
||||
public void push(T item) {
|
||||
lock.lock();
|
||||
stc.push(item);
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void pop() {
|
||||
lock.lock();
|
||||
stc.pop();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
class FaultySyncStackExample<T> {
|
||||
private Lock lock = new ReentrantLock();
|
||||
private Stack<T> stc = new Stack<T>();
|
||||
|
||||
public void push(T item) {
|
||||
lock.lock();
|
||||
stc.push(item);
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void pop() {
|
||||
stc.pop(); // $ Alert
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class SynchronizedAndLock {
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
private int length = 0; // $ Alert
|
||||
|
||||
public void add(int value) {
|
||||
lock.lock();
|
||||
length++;
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public synchronized void subtract() {
|
||||
length--;
|
||||
}
|
||||
}
|
||||
76
java/ql/test/query-tests/ThreadSafe/examples/Test.java
Normal file
76
java/ql/test/query-tests/ThreadSafe/examples/Test.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package examples;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class Test {
|
||||
/**
|
||||
* Escaping field due to public visibility.
|
||||
*/
|
||||
int publicField;
|
||||
|
||||
private int y;
|
||||
final int immutableField = 1;
|
||||
|
||||
// As of the below examples with synchronized as well. Except the incorrectly placed lock.
|
||||
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* Calls the a method where y field escapes.
|
||||
* @param y
|
||||
*/
|
||||
public void setYAgainInCorrect(int t) {
|
||||
setYPrivate(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the method where y field escapes.
|
||||
* @param y
|
||||
*/
|
||||
public void setYAgainCorrect(int y) {
|
||||
lock.lock();
|
||||
setYPrivate(y);
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* No escaping y field. Locks the y before assignment.
|
||||
* @param y
|
||||
*/
|
||||
public void setYCorrect(int y) {
|
||||
lock.lock();
|
||||
this.y = y;
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* No direct escaping, since it method is private. Only escaping if another public method uses this.
|
||||
* @param y
|
||||
*/
|
||||
private void setYPrivate(int y) {
|
||||
this.y = y; // $ Alert
|
||||
}
|
||||
|
||||
/**
|
||||
* Incorrectly locks y.
|
||||
* @param y
|
||||
*/
|
||||
public void setYWrongLock(int y) {
|
||||
this.y = y; // $ Alert
|
||||
lock.lock();
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public synchronized int getImmutableField() {
|
||||
return immutableField;
|
||||
}
|
||||
|
||||
public synchronized int getImmutableField2() {
|
||||
return immutableField;
|
||||
}
|
||||
|
||||
public void testMethod() {
|
||||
this.y = y + 2; // $ Alert
|
||||
}
|
||||
}
|
||||
22
java/ql/test/query-tests/ThreadSafe/examples/Test2.java
Normal file
22
java/ql/test/query-tests/ThreadSafe/examples/Test2.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package examples;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
// Note: Not marked as thread-safe
|
||||
// We inherit from this in Test3Super.java
|
||||
public class Test2 {
|
||||
int x;
|
||||
protected ArrayList<String> lst = new ArrayList<>();
|
||||
|
||||
public Test2() {
|
||||
this.x = 0;
|
||||
}
|
||||
|
||||
public void changeX() {
|
||||
this.x = x + 1;
|
||||
}
|
||||
|
||||
public void changeLst() {
|
||||
lst.add("Hello");
|
||||
}
|
||||
}
|
||||
17
java/ql/test/query-tests/ThreadSafe/examples/Test3Super.java
Normal file
17
java/ql/test/query-tests/ThreadSafe/examples/Test3Super.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package examples;
|
||||
|
||||
@ThreadSafe
|
||||
public class Test3Super extends Test2 { // We might want an alert here for the inherited unsafe methods.
|
||||
|
||||
public Test3Super() {
|
||||
super.x = 0;
|
||||
}
|
||||
|
||||
public void y() {
|
||||
super.x = 0; //$ MISSING: Alert
|
||||
}
|
||||
|
||||
public void yLst() {
|
||||
super.lst.add("Hello!"); //$ MISSING: Alert
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package examples;
|
||||
|
||||
public @interface ThreadSafe {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package examples;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ThreadSafe
|
||||
public class TurnstileExample {
|
||||
private Lock lock = new ReentrantLock();
|
||||
private int count = 0;
|
||||
|
||||
public void inc() {
|
||||
Lock l = lock;
|
||||
l.lock();
|
||||
count++;
|
||||
l.unlock();
|
||||
}
|
||||
|
||||
public void dec() {
|
||||
lock.lock();
|
||||
count--;
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user