-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathEmptyRunMethodInThread.ql
More file actions
62 lines (57 loc) · 2.21 KB
/
EmptyRunMethodInThread.ql
File metadata and controls
62 lines (57 loc) · 2.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* @name Useless run() method in thread
* @description Thread instances that neither get an argument of type 'Runnable' passed to their
* constructor nor override the 'Thread.run' method are likely to have no effect.
* @kind problem
* @problem.severity warning
* @precision low
* @id java/empty-run-method-in-thread
* @tags reliability
* correctness
* concurrency
*/
import java
class ThreadClass extends Class {
ThreadClass() { this.hasQualifiedName("java.lang", "Thread") }
/**
* Any constructor of `java.lang.Thread` _without_ a parameter of type `Runnable`;
* these require overriding the `Thread.run()` method in order to do anything useful.
*/
Constructor getAConstructorWithoutRunnableParam() {
result = this.getAConstructor() and
(
result.getNumberOfParameters() = 0
or
result.getNumberOfParameters() = 1 and
result.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "String")
or
result.getNumberOfParameters() = 2 and
result.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "ThreadGroup") and
result.getParameter(1).getType().(RefType).hasQualifiedName("java.lang", "String")
)
}
/**
* Any constructor of `java.lang.Thread` _with_ a parameter of type `Runnable`;
* these ensure that the `Thread.run()` method calls the `Runnable.run()` method.
*/
Constructor getAConstructorWithRunnableParam() {
result = this.getAConstructor() and
not exists(Constructor c | c = result | result = this.getAConstructorWithoutRunnableParam())
}
}
from ClassInstanceExpr cie, ThreadClass thread, Class emptythread
where
emptythread.hasSupertype*(thread) and
not exists(Class middle, Method run |
run.hasName("run") and
run.isPublic() and
not run.isAbstract() and
run.hasNoParameters() and
middle.getAMethod() = run and
middle.hasSupertype+(thread) and
emptythread.hasSupertype*(middle)
) and
not cie.getConstructor().callsConstructor*(thread.getAConstructorWithRunnableParam()) and
cie.getType().(RefType).getSourceDeclaration() = emptythread
select cie,
"Thread " + emptythread.getName() + " has a useless empty run() inherited from java.lang.Thread."