Java requires that each method must address every checked exception that can be thrown during its execution either by handling the exception within a try-catch
block or by declaring that the exception can propagate out of the method (via the throws
clause). Unfortunately, undeclared checked exceptions can be thrown at runtime. Consequently, callers cannot statically use the throws
clause to determine the complete set of checked exceptions that could propagate from an invoked method.
Wiki Markup |
---|
A common argument favoring undeclared checked exceptions (even unchecked exceptions) is that the caller does not have to define innumerable {{catch}} blocks 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, appropriate for the abstraction level. For example, a method may throw an {{IOException}} instead of specific exceptions such as {{FileNotFoundException}}. While exception handling should be as specific as possible, a compromise can be struck this way, to increase the code readability in complex systems \[[Venners 2003|AA. Bibliography#Venners 03]\]. However, wrapping checked exceptions into a broader exception class may not provide enough context for a recovery at the top level. Unchecked exceptions and undeclared checked exceptions, on the other hand, help reduce clutter in code but are unsuitable when a client is expected to recover from an exceptional condition. |
David: your paragraph about checked vs. unchecked exceptions goes here.
Clients or callers need to know which exceptions Clients or callers are expected to know the exceptions that the underlying code can throw. For this reasonConsequently, developers should – and developers of security critical software must — sufficiently document all possible unchecked and undeclared checked exceptions. Undeclared checked exceptions need diligent documentation. Security critical software must make this contract explicit. Yet another difficulty in dealing with undeclared checked exceptions is that sensitive exceptions cannot be sanitized before delivery, in the absence of a dedicated exception reporter. For these reasons, undeclared checked exceptions should be avoidedthat can be thrown by a method.
Noncompliant Code Example
This noncompliant code example is insecure both because it can throw undeclared checked exceptions and also because it uses the sun.misc.Unsafe
class. All sun.*
classes are unsupported and undocumented because using them their use can cause portability and backward compatibility issues. This noncompliant code example is insecure from this standpoint and from its ability to throw undeclared checked exceptions.
Classes that are A class that is loaded by the bootstrap class loader has have the authority permissions needed to call the static
factory method Unsafe.getUnsafe()
. An average developer may be unable to fulfill this requirement unless Arranging to have an arbitrary class loaded by the bootstrap class loader without modifying the sun.boot.class.path
system property is modified. One alternative can be difficult. However, an alternative way to gain access is to change the accessibility of the field that holds an instance of Unsafe
using through the use of reflection. This is only possible if works only when permitted by the current security manager allows it (by violating (which would violate guideline ENV04-J. Do not grant ReflectPermission with target suppressAccessChecks.) To Given access to Unsafe
, a call can throw an undeclared checked exception , the caller just needs to use by calling the Unsafe.throwException()
method.
...
Any checked exception thrown by the default constructor of Class.newInstance()
is 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
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 exceptions, whether checked or unchecked.
Code Block | ||
---|---|---|
| ||
public class BadNewInstance { private static Throwable throwable; private BadNewInstance() throws Throwable { throw throwable; } public static synchronized void undeclaredThrow(Throwable throwable) { // These two should not be passed if (throwable instanceof IllegalAccessException || throwable instanceof InstantiationException) { throw new IllegalArgumentException(); // Unchecked, no declaration required } BadNewInstance.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; see JavaDoc BadNewInstance.class.newInstance(); } catch (InstantiationException e) { /* dead codeunreachable */ } catch (IllegalAccessException e) { /* deadunreachable code */ } finally { // Avoid memory leak BadNewInstance.throwable = null; } } } public class UndeclaredException { public static void main(String[] args) { // No declared checked exceptions BadNewInstance.undeclaredThrow(new Exception("Any checked exception")); } } |
Even if When the programmer wishes to 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 A simple workaround is to catch Exception
and dynamically check whether the possible checked caught exception is an instance of it else re-throw the exception. This is shown below. The most obvious pitfall is that this technique is easy to bypass whenever an unanticipated checked exception is thrownthe possible checked exception (carefully re-throwing all other exceptions, of course), as shown below. This approach is fragile, because any unanticipated checked exception bypasses the dynamic check.
Code Block |
---|
public static void main(String[] args) { try { BadNewInstance.undeclaredThrow(new IOException("Any checked exception")); } catch(Exception e) { if (e instanceof IOException) { System.out.println("IOException occurred"); } else if (e instanceof RuntimeException) { throw (RuntimeException) e; } else { //some other unknown checked exception } } } |
Compliant Solution
Wiki Markup |
---|
PreferUse the method {{Constructor.newInstance()}} overrather than {{Class.newInstance()}}. An alternative is to use The {{java.lang.reflect.Constructor.newInstance()}} method wraps any exceptions thrown from within the constructor into a checked exception called {{InvocationTargetException}}. Use of the builder interface recommended by Bloch \[[Bloch 2008|AA. Bibliography#Bloch 08]\] is an acceptable alternative. |
Code Block | ||
---|---|---|
| ||
// Generic type for a builder used to build any object of type T public interface Builder<T> { public T build(); } |
...
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 thisthe class is used \[[Roubtsov 2003|AA. Bibliography#Roubtsov 03]\]. Simply,Compiling compiling against a class that declares the checked exception and supplying one at runtime a class that doesn't,lacks the declaration also suffices. Similarly, a differentcompiler compilerother than {{javac}} might handle checked exceptions differently. YetUndeclared anotherchecked wayexceptions tocan allowalso undeclaredbe checkedproduced exceptionsthrough iscrafted touse furtivelyof use the {{sun.corba.Bridge}} class. All these methods are strongly discouraged. |
...
Refrain from employing code (whether legitimate or hostile) that is capable of throwing can throw undeclared checked exceptions. If the source code can throw themWhen this is unavoidable, explicitly document the behavior. Finally, do not never use deprecated methods such as Thread.stop()
(as required by MET15-J. Do not use deprecated or obsolete classes or methods).
Risk Assessment
Failure to document undeclared checked exceptions can result in checked exceptions that the caller is unprepared to handle. This violates , consequently violating the safety property.
Guideline | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXC10-J | low | unlikely | high | P1 | L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Bibliography
Wiki Markup |
---|
\[[JLSBloch 20052008|AA. Bibliography#JLSBibliography#Bloch 0508]\] ChapterItem 112: Exceptions \[[Venners 2003|AA. Bibliography#Venners 03]\] "Scalability of Checked Exceptions" \[[Roubtsov 2003|AA. Bibliography#Roubtsov 03]\] \[[Schwarz 2004|AA. Bibliography#Schwarz 04]\]"Consider a builder when faced with many constructor parameters" \[[Goetz 2004b|AA. Bibliography#Goetz 04b]\] \[[BlochJLS 20082005|AA. Bibliography#BlochBibliography#JLS 0805]\] ItemChapter 211: "Consider a builder when faced with many constructor parameters"Exceptions \[[MITRE 2009|AA. Bibliography#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" \[[Roubtsov 2003|AA. Bibliography#Roubtsov 03]\] \[[Schwarz 2004|AA. Bibliography#Schwarz 04]\] \[[Venners 2003|AA. Bibliography#Venners 03]\] "Scalability of Checked Exceptions" |
...
EXC09-J. Prevent inadvertent calls to System.exit() or forced shutdown 06. Exceptional Behavior (EXC) EXC11-J. Restore prior object state on method failure