You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 53 Next »

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 2008]. It is permissible to use the @SuppressWarnings("unchecked") annotation to suppress unchecked warnings when, and only when, the warning-emitting code is guaranteed to be type safe. A common use case is mixing legacy code with new client code. The perils of ignoring unchecked warnings are discussed extensively in OBJ03-J. Do not mix generic with nongeneric raw types in new code.

According to the Java API [java:API 2006], Annotation Type SuppressWarnings documentation,

As a matter of style, programmers should always use this annotation on the most deeply nested element where it is effective. If you want to suppress a warning in a particular method, you should annotate that method rather than its class.

The @SuppressWarnings annotation can be used in the declaration of variables and 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 code example, the @SuppressWarnings annotation's scope encompasses the whole class. This is dangerous because all unchecked warnings within the class will be suppressed. Oversights of this nature can lead to a ClassCastException at runtime.

@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.

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 code example is from the implementation of java.util.ArrayList. When the class is compiled, it emits an unchecked cast warning, as shown. Because the return statement is not a declaration, the Java Language Specification [JLS 2005] makes it impossible to suppress the warning trivially. Consequently, the @SuppressWarnings is used over method scope. This can cause issues when some functionality that performs type-unsafe operations is added to the method at a later date [Bloch 2008].

@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
  if (a.length < size)
    return (T[]) Arrays.copyOf(elements, size, a.getClass()); // Produces unchecked warning
 // ...
}
// 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, as in the preceding noncompliant code example, declare a new variable to hold the return value and adorn it with the @SuppressWarnings annotation.

// ...
@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.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MSC07-J

medium

probable

high

P4

L3

Automated Detection

This rule cannot be statically enforced in full generality; static analysis could be possible for some interesting special cases.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Bibliography

[Bloch 2008] Item 24: "Eliminate unchecked warnings"


      49. Miscellaneous (MSC)      MSC52-J. Do not place a semicolon on the same line as an if, for, or while statement

  • No labels