-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Java: Queries for thread-safe classes #19539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
886f5b2
to
d32cd70
Compare
QHelp previews: java/ql/src/Likely Bugs/Concurrency/Escaping.qhelpEscapingIn a thread-safe class, non-final fields should generally be private (or possibly volatile) to ensure that they cannot be accessed by other threads in an unsafe manner. RecommendationIf the field does not change, mark it as References
java/ql/src/Likely Bugs/Concurrency/SafePublication.qhelpSafe publicationIn a thread-safe class, values must be published safely to avoid inconsistent or unexpected behavior caused by visibility issues between threads. If a value is not safely published, one thread may see a stale or partially constructed value written by another thread, leading to subtle concurrency bugs. In particular, values of primitive types should not be initialised to anything but their default values (which for Techniques for safe publication include:
RecommendationChoose a safe publication technique that fits your use case. If the value only needs to be written once, say for a singleton, consider using the ExampleIn the following example, the value of @ThreadSafe
public class UnsafePublication {
private Object value;
public void produce() {
value = new Object(); // Not safely published, other threads may see the default value null
}
public Object getValue() {
return value;
}
} To fix this example, declare the field public class SafePublication {
private Object value;
public synchronized void produce() {
value = new Object(); // Safely published using synchronization
}
public synchronized Object getValue() {
return value;
}
} References
java/ql/src/Likely Bugs/Concurrency/ThreadSafe.qhelpNot thread-safeIn a thread-safe class, all field accesses that can be caused by calls to public methods must be properly synchronized. RecommendationProtect the field access with a lock. Alternatively mark the field as References
|
d32cd70
to
126f974
Compare
Co-authored-by: Raúl Pardo <raul.pardo@protonmail.com> Co-authored-by: SimonJorgensenMancofi <simon.jorgensen@mancofi.dk> Co-authored-by: Bjørnar Haugstad Jåtten <bjornjaat@hotmail.com>
Our monitor analysis would be fooled by cycles in the call graph, since it required all edges on a path to a conflicting access to be either - targetting a method where the access is monitored (recursively) or - monitored locally, that is the call is monitored in the calling method For access to be monitored (first case) all outgoing edges (towards an access) need to satisfy this property. For a loop, that is too strong, only edges out of the loop actually need to be protected. This led to FPs.
126f974
to
c2374e5
Compare
Identified by triage of DCA results. Previously, we did not use the erased type, so would not recgnize `CompletableFuture<R>`. We now also recognize safe initializers.
Commented offline. |
This PR introduces three queries for thread-safe classes, corresponding to three properties that such classes must possess, known as
Each query is introduced in its own commit, P3 first since it comes with some definitions that make P2 and P1 simple to write. And then there is a fourth commit fixing up the query for P3, since its detection in the first version only works when there are no loops in the call graph. I chose to show both versions, since the first is quite simple to understand and the second is basically the same idea but operating on SCCs of the call graph.
Some considerations:
Monitors
be moved intoconcurrency.qll
?error
?