Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

It is mandatory to handle checked exceptions in Java. The compiler enforces this rule by making sure that every possible checked exception is either declared using the throws clause or handled Java requires that each method address every checked exception that can be thrown during its execution either by handling the exception within a try-catch block . Unfortunately, this guarantee does not carry over to the JVM runtime environment, depriving the caller from critical information about the exceptions that the callee is capable of throwing.

Checked exceptions can be thought of as a checklist of unusual events that can be handled during program execution whereas unchecked exceptions involve programming mistakes that should be caught early, without relying on the Java runtime to make a recovery. Undeclared checked exceptions resemble the latter in behavior since the compiler does not force the programmer to handle them.

Wiki Markup
A common argument favoring undeclared checked exceptions (even unchecked exceptions) is that the caller does not have to define innumerable exception handlers for each specific checked exception that the callee can throw. Likewise, handling each exception within the callee is believed to clutter-up the code. One way to deal with this issue is to wrap the specific exceptions into a new exception. While exception handling should be as specific as possible, a compromise can be struck to increase the code readability in complex systems \[[Venners 03|AA. Java References#Venners 03]\]. Wrapping checked exceptions into a broader exception class may not provide enough context for a recovery at the top level. On the other hand, bringing unchecked exceptions into the picture may not be the road to success. 

Clients or callers are expected to know the exceptions that the underlying code can throw. For this reason, developers must sufficiently document all possible checked exceptions. Undeclared checked exceptions are a special class of exceptions that need diligent documentation. Security critical software must almost always make this contract explicit. Yet another difficulty in dealing with them is that sensitive exceptions cannot be sanitized before delivery. Ideally, undeclared checked exceptions should be avoided.

Noncompliant Code Example

This noncompliant code example uses the sun.misc.Unsafe class. All sun.* classes are not documented on purpose since using them can cause portability and backward compatibility issues. This code fragment proves risky not only from this standpoint; its malevolence is aggravated with the capability of throwing undeclared checked exceptions.

A class that is loaded by the bootstrap class loader has the authority to call the static factory method Unsafe.getUnsafe(). An average developer would not be able to fulfill this requirement unless the sun.boot.class.path system property is modified. One alternative is to change the accessibility of the field that holds an instance of Unsafe using reflection. This is only possible if the current security manager allows it (by violating SEC32-J. Do not grant ReflectPermission with action suppressAccessChecks). To throw an undeclared checked exception, the caller just needs to use the Unsafe.throwException() method.

Code Block
bgColor#FFcccc

import java.io.IOException;
import java.lang.reflect.Field;
import sun.misc.Unsafe;

public class UnsafeCode {
  public static void main( String[] args ) throws SecurityException, NoSuchFieldException,
  IllegalArgumentException, IllegalAccessException {
    Field f = Unsafe.class.getDeclaredField("theUnsafe");
    field.setAccessible(true);
    Unsafe u =  (Unsafe) field.get(null);
    u.throwException(new IOException("No need to declare this checked exception"));
  }
}

Noncompliant Code Example

Any checked exception that is thrown by the default constructor of Class.NewInstance gets propagated even if it is not declared explicitly. On the contrary, the java.lang.reflect.Constructor.NewInstance() method wraps any exceptions thrown from within the constructor into a checked exception called InvocationTargetException.

or by declaring that the exception can propagate out of the method (via the throws clause). Unfortunately, there are a few techniques that permit undeclared checked exceptions to be thrown at runtime. Such techniques defeat the ability of caller methods to use the throws clause to determine the complete set of checked exceptions that could propagate from an invoked method. Consequently, such techniques must not be used to throw undeclared checked exceptions.

Noncompliant Code Example (Class.newInstance())

This noncompliant code example throws undeclared checked exceptions. The undeclaredThrow() method takes a Throwable argument and invokes a function that will throw the argument without declaring it. Although undeclaredThrow() catches any exceptions the function declares that it might throw, it nevertheless throws the argument it is given without regard to whether the argument is one of the declared exceptions. This noncompliant code example also violates ERR07-J. Do not throw RuntimeException, Exception, or Throwable. However, because of exception ERR08-J-EX0, it does not violate ERR08-J. Do not catch NullPointerException or any of its ancestors.
Any checked exception thrown by the default constructor of java.lang.Class.newInstance() is propagated to the caller even though Class.newInstance() declares that it throws only InstantiationException and IllegalAccessException. This noncompliant code example demonstrates one way to use Class.newInstance() to throw arbitrary checked and unchecked exceptions:

Code Block
bgColor#FFcccc
public class NewInstance
Code Block
bgColor#FFcccc

public class BadNewInstance {
  private static Throwable throwable;

  private BadNewInstanceNewInstance() throws Throwable {
    throw throwable;
  }

  public static synchronized void undeclaredThrow(Throwable throwable) {
    // theseThese twoexceptions should not be passed
    if (throwable instanceof IllegalAccessException ||
        throwable instanceof InstantiationException) {
        throw new IllegalArgumentException(); // uncheckedUnchecked, no declaration required
      throw new IllegalArgumentException(); 
    }

   BadNewInstance NewInstance.throwable = throwable;
    try {
      // Next line throws the Throwable argument passed in above,
      // even though the throws clause of class.newInstance fails
      // to declare that this may happen
      BadNewInstanceNewInstance.class.newInstance();
    } catch (InstantiationException e) { /* dead codeUnreachable */ } 
     } catch (IllegalAccessException e) { /* deadUnreachable code */
    } 
   finally { // Avoid memory leak
    finally { BadNewInstanceNewInstance.throwable = null; }
  // avoid memory leak}
  }
}

public class UndeclaredException {
  public static void main(String[] args) {   
    // noNo declared checked exceptions
    BadNewInstanceNewInstance.undeclaredThrow(
        new Exception("Any checked exception"));
  }
}

Noncompliant Code Example (Class.newInstance() Workarounds)

When Even if the programmer now wishes to capture catch and handle the possible undeclared checked exceptions, the compiler refuses to believe that any can be thrown in the particular context. One way to deal with this difficulty is to catch Exception and check whether the possible checked This noncompliant code example attempts to catch undeclared checked exceptions thrown by Class.newInstance(). It catches Exception and dynamically checks whether the caught exception is an instance of it else re-throw the exception. This is shown below. The most obvious pitfall is that this technique would be easy to bypass whenever an unanticipated checked exception gets thrownthe possible checked exception (carefully rethrowing all other exceptions).

Code Block
bgColor#FFcccc

  public static void main(String[] args) {
    try {	
      BadNewInstanceNewInstance.undeclaredThrow(
        new IOException("Any checked exception"));
  } catch }catch(ExceptionThrowable e) { 
    if (e instanceof IOException) {
      System.out.println("IOException occurred");
    } else if (e instanceof RuntimeException) {
      throw (RuntimeException) e;
    } else {
      //some otherForward unknownto checked exceptionhandler
    }
  }
}  

Compliant Solution

...

Wiki Markup
Prefer {{Constructor.newInstance}} over {{Class.newInstance}}. An alternative is to use the builder interface recommended by \[[Bloch 08|AA. Java References#Bloch 08]\]. 

Code Block
bgColor#ccccff

// Generic type for a builder used to build any object of type T
public interface Builder<T> {
 public T build();
}

A client can pass a builder to a method and request the creation of an object. A bounded wildcard type should be used to constrain the builder's type parameter. In the code snippet that follows, a US Dollar (USD) is built from coins of different denomination.

Code Block

USD buildCurrency(Builder<? extends denomination> currencyBuilder) { /* ... */ }

For further details on implementing the builder pattern, refer to OBJ32-J. Do not allow partially initialized objects to be accessed. In the example describe in that rule, the Currency.Builder class must implement the Builder interface highlighted in this recommendation.

(Constructor.newInstance())

This compliant solution uses java.lang.reflect.Constructor.newInstance() rather than Class.newInstance(). The Constructor.newInstance() method wraps any exceptions thrown from within the constructor into a checked exception called InvocationTargetException.

Code Block
bgColor#ccccff
public static synchronized void undeclaredThrow(Throwable throwable) {
  // These exceptions should not be passed
  if (throwable instanceof IllegalAccessException ||
      throwable instanceof InstantiationException) {
    // Unchecked, no declaration required
    throw new IllegalArgumentException(); 
  }

  NewInstance.throwable = throwable;
  try {
    Constructor constructor =
        NewInstance.class.getConstructor(new Class<?>[0]);
    constructor.newInstance();
  } catch (InstantiationException e) { /* Unreachable */
  } catch (IllegalAccessException e) { /* Unreachable */
  } catch (InvocationTargetException e) {
    System.out.println("Exception thrown: "
        + e.getCause().toString());
  } finally { // Avoid memory leak
    NewInstance.throwable = null;
  }
}

Noncompliant Code Example (sun.misc.Unsafe)

This noncompliant code example is insecure both because it can throw undeclared checked exceptions and because it uses the sun.misc.Unsafe class. All sun.* classes are unsupported and undocumented because their use can cause portability and backward compatibility issues.

Classes loaded by the bootstrap class loader have the permissions needed to call the static factory method Unsafe.getUnsafe(). Arranging to have an arbitrary class loaded by the bootstrap class loader without modifying the sun.boot.class.path system property can be difficult. However, an alternative way to gain access is to change the accessibility of the field that holds an instance of Unsafe through the use of reflection. This approach works only when permitted by the current security manager (which would violate ENV03-J. Do not grant dangerous combinations of permissions). Given access to Unsafe, a program can throw an undeclared checked exception by calling the Unsafe.throwException() method.

Code Block
bgColor#FFcccc
import java.io.IOException;
import java.lang.reflect.Field;
import sun.misc.Unsafe;

public class UnsafeCode {
  public static void main(String[] args)
      throws SecurityException, NoSuchFieldException,
             IllegalArgumentException, IllegalAccessException {
    Field f = Unsafe.class.getDeclaredField("theUnsafe");
    f.setAccessible(true);
    Unsafe u = (Unsafe) f.get(null);
    u.throwException(new IOException("No need to declare this checked exception"));
  }
}

Noncompliant Code Example (Generic Exception)

...

An unchecked cast of a generic type with parameterized exception declaration can also result in unexpected checked exceptions. The compiler complains All such casts are diagnosed by the compiler unless the warnings are suppressed.

Code Block
bgColor#FFcccc

interface Thr<EXC extends Exception> {
    void fn() throws EXC;
}

public class UndeclaredGen {
  static void undeclaredThrow() throws RuntimeException {
    @SuppressWarnings("unchecked")  // suppressesSuppresses warnings  
    Thr<RuntimeException> thr = (Thr<RuntimeException>)(Thr)
      new Thr<IOException>() {
        public void fn() throws IOException {
          throw new IOException();
	}
      };
      thr.fn();
    }

  public static void main(String[] args) {
    undeclaredThrow();
  }
}

Noncompliant Code Example

...

(Thread.stop(Throwable))

According to \the Java API [[API 06|AA. Java References#API 06]\] class {{Thread}} documentation, API 2014], class Thread:

Wiki Markup\[Thread.stop()\] may be used to generate exceptions that its target thread is unprepared to handle (including checked exceptions that the thread could not possibly throw, were it not for this method). For example, the following method is behaviorally identical to Java's throw operation, but circumvents the compiler's attempts to guarantee that the calling method has declared all of the checked exceptions that it may ] This method was originally designed to force a thread to stop and throw a given Throwable as an exception. It was inherently unsafe (see Thread.stop() for details), and furthermore could be used to generate exceptions that the target thread was not prepared to handle.

For example, the following method is behaviorally identical to Java's throw operation but circumvents the compiler's attempts to guarantee that the calling method has declared all of the checked exceptions that it may throw.

Code Block
bgColor#FFcccc

static void sneakyThrow(Throwable t) {
  Thread.currentThread().stop(t);
}

Wiki Markup
It is also possible to disassemble a class, remove any declared checked exceptions and reassemble the class so that checked exceptions are thrown at runtime when this class is used \[[Roubtsov 03|AA. Java References#Roubtsov 03]\]. Simply, compiling against a class that declares the checked exception and supplying one at runtime that doesn't also suffices. Similarly, a different compiler than {{javac}} might handle checked exceptions differently. Yet another way is to furtively use the {{sun.corba.Bridge}} class. All these methods are strongly discouraged.  

Compliant Solution

Note that the Thread.stop() methods are deprecated, so this code also violates MET02-J. Do not use deprecated or obsolete classes or methods.

Noncompliant Code Example (Bytecode Manipulation)

It is also possible to disassemble a class, remove any declared checked exceptions, and reassemble the class so that checked exceptions are thrown at runtime when the class is used [Roubtsov 2003]. Compiling against a class that declares the checked exception and supplying at runtime a class that lacks the declaration can also result in undeclared checked exceptions. Undeclared checked exceptions can also be produced through crafted use of the sun.corba.Bridge class. All of these practices are violations of this rule.Refrain from employing code that is capable of throwing undeclared checked exceptions (legitimate or hostile). If the source code can throw them, explicitly document the behavior. Finally, do not use deprecated methods such as Thread.stop().

Risk Assessment

Failure to document undeclared checked exceptions can lead to result in checked exceptions that the caller is unprepared to handle, consequently violating the safety property.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXC06ERR06-J

low Low

unlikely Unlikely

high High

P1

L3

Automated Detection

TODO

Related Vulnerabilities

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

References

Wiki Markup
\[[JLS 05|AA. Java References#JLS 05]\] Chapter 11: Exceptions
\[[Venners 03|AA. Java References#Venners 03]\] "Scalability of Checked Exceptions"
\[[Roubtsov 03|AA. Java References#Roubtsov 03]\]
\[[Schwarz 04|AA. Java References#Schwarz 04]\]
\[[Goetz 04b|AA. Java References#Goetz 04b]\]
\[[Naftalin 06b|AA. Java References#Naftalin 06b]\] "Principle of Indecent Exposure"
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 2: "Consider a builder when faced with many constructor parameters"
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 703|http://cwe.mitre.org/data/definitions/703.html] "Failure to Handle Exceptional Conditions", [CWE ID 248|http://cwe.mitre.org/data/definitions/248.html] "Uncaught Exception"

Related Guidelines

MITRE CWE

CWE-703, Improper Check or Handling of Exceptional Conditions
CWE-248, Uncaught Exception

Bibliography

[API 2014]Thread.stop(Throwable)

[Bloch 2008]

Item 2, "Consider a Builder When Faced with Many Constructor Parameters"

[Goetz 2004b]

 

[JLS 2015]

Chapter 11, "Exceptions"

[Roubtsov 2003]

 

[Schwarz 2004]

 

[Venners 2003]

"Scalability of Checked Exceptions"

 

...

Image Added Image Added Image Added

 EXC05-J. Use a class dedicated to reporting exceptions      10. Exceptional Behavior (EXC)      10. Exceptional Behavior (EXC)