The compiler issues unchecked warnings when it detects potential type safety issues arising from mixing raw types with generic code. This includes unchecked cast warnings, unchecked method invocation warnings, unchecked generic array creation warnings and unchecked conversion warnings [Bloch 08]. It is permissible to use the @SuppressWarnings("unchecked")
annotation to suppress unchecked warnings if and only if the warning emitting code is guaranteed to be typesafe. A common usecase is mixing legacy code with new client code. The perils of relaxing unchecked warnings are discussed extensively in MSC10-J. Avoid mixing generic and non-generic code if possible.
The @SuppressWarnings
annotation can be used in the declaration of variables, methods as well as an entire class. It is however, very important to narrow down its scope so that other noteworthy warnings within the same scope are not silently ignored.
Noncompliant Code Example
In this noncompliant example, the @SuppressWarnings
annotation's scope encompasses the whole class. This is dangerous as all unchecked warnings within the class will be suppressed. Oversights of this nature can lead to a ClassCastException
at runtime.
Code Block | ||
---|---|---|
| ||
@SuppressWarnings("unchecked") class Legacy {
Set s = new HashSet();
public final void doLogic(int a,char c) {
s.add(a);
s.add(c); // type unsafe operation, ignored
}
}
|
Compliant Solution
Limit the scope of the @SuppressWarnings
annotation to the nearest unchecked warning generating code. In this case, it may be used in the declaration for the Set
.
Code Block | ||
---|---|---|
| ||
class Legacy {
@SuppressWarnings("unchecked") Set s = new HashSet();
public final void doLogic(int a,char c) {
s.add(a); //produces unchecked warning
s.add(c); // produces unchecked warning
}
}
|
Noncompliant Code Example
This noncompliant example is from the implementation of java.util.ArrayList
. When the class is compiled, it emits an unchecked cast warning, as shown. Since the return
statement is not a declaration, the Java Language Specification [JLS 05] makes it impossible to suppress the warning trivially. Therefore, the @SuppressWarnings
has been used over method scope. This is can cause issues when some functionality that performs type-unsafe operations is added to the method at a later date. [Bloch 08]
Code Block | ||
---|---|---|
| ||
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
return (T[]) Arrays.copyOf(elements, size, a.getClass()); // produces unchecked warning
// ...
}
|
Code Block |
---|
// Unchecked cast warning
ArrayList.java:305: warning: [unchecked] unchecked cast found : Object[], required: T[]
return (T[]) Arrays.copyOf(elements, size, a.getClass());
|
Compliant Solution
When it is impossible to use the @SuppressWarnings
annotation, such as in the case of the preceding noncompliant code example, declare a new variable to hold the return value and adorn it with the @SuppressWarings
annotation.
Code Block | ||
---|---|---|
| ||
// ...
@SuppressWarnings("unchecked") T[] result =
(T[]) Arrays.copyOf(elements, size, a.getClass());
return result;
// ...
|
Risk Assessment
Failure to reduce the scope of the @SuppressWarnings
annotation can lead to runtime exceptions and break type safety guarantees.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
SCP04-J | medium | probable | high | P4 | L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[Bloch 08] Item 24: "Eliminate unchecked warnings"<stub>