Skip to content

Commit f88daff

Browse files
committed
Java: note that classes with entirely private constructors can't be subclassed
1 parent fa8cbee commit f88daff

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515

1616
import java
1717

18+
private predicate hasASubclass(RefType t) {
19+
exists(RefType sub | sub != t | sub.getAnAncestor() = t)
20+
}
21+
1822
/**
1923
* Holds if this type is either `final` or
2024
* `private` and without subtypes.
@@ -24,7 +28,11 @@ private predicate cannotBeExtended(RefType t) {
2428
or
2529
// If the class is private, all possible subclasses are known.
2630
t.isPrivate() and
27-
not exists(RefType sub | sub != t | sub.getAnAncestor() = t)
31+
not hasASubclass(t)
32+
or
33+
// If the class only has private constructors, all possible subclasses are known.
34+
forex(Constructor c | c.getDeclaringType() = t | c.isPrivate()) and
35+
not hasASubclass(t)
2836
}
2937

3038
from MethodCall m, Constructor c, Class clazz

java/ql/test/query-tests/StartInConstructor/Test.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,18 @@ public Private() {
3030
}
3131

3232
}
33-
}
33+
34+
public static class AllPrivateConstructors {
35+
Thread myThread;
36+
37+
private AllPrivateConstructors() {
38+
myThread = new Thread("myThread");
39+
// OK - class cannot be extended outside this file, and is not in fact extended
40+
myThread.start();
41+
}
42+
43+
public static AllPrivateConstructors create() {
44+
return new AllPrivateConstructors();
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)