Programmers often suppress checked exceptions by catching exceptions with an empty or trivial catch
block. Each catch
block must ensure that the program continues only with valid invariants. Consequently, the catch
block must either recover from the exceptional condition, rethrow the exception to allow the next nearest enclosing catch
clause of a try
statement to recover, or throw an exception that is appropriate to the context of the catch
block.
fall into the trap of suppressing or ignoring checked exceptions. Unless there is a valid reason for ignoring exceptions, such as the client cannot be expected to stage a recovery, it is important to handle them appropriately. Catching and suppressing exceptions is considered bad practice for several reasons. Exceptions disrupt the expected control flow of the application. For example, statements that occur no part of any expression or statement that occurs in the try
block after the statement that caused point from which the exception , do not execute as required. To ensure that the program does not resume with invalid invariants, the catch
block should immediately stop control flow from proceeding, instead of ignoring or suppressing the exception. If the program is capable of recovering from the exceptional condition, the statements in the try
block that are required to be executed, must be moved outside the try
blockis thrown is evaluated. Consequently, exceptions must be handled appropriately. Many reasons for suppressing exceptions are invalid. For example, when the client cannot be expected to recover from the underlying problem, it is good practice to allow the exception to propagate outwards rather than to catch and suppress the exception.
Noncompliant Code Example
This noncompliant code example adorns the catch
block with an ignore comment and forgoes appropriate exception handling.simply prints the exception's stack trace:
Code Block | ||
---|---|---|
| ||
try { //... } catch (IOException ioe) { // Ignore ioe.printStackTrace(); } |
Noncompliant Code Example
Printing the exception's stack trace can be useful for debugging purposes, but the resulting program execution is equivalent to ignoring suppressing the exception, as this noncompliant code example demonstrates.
Code Block | ||
---|---|---|
| ||
try {
//...
} catch(IOException ioe) {
ioe.printStacktrace();
}
|
Note that even though the application . Printing the stack trace can also leak information about the structure and state of the process to an attacker (see ERR01-J. Do not allow exceptions to expose sensitive information for more information). Note that even though this noncompliant code example reacts to the exception by printing out a stack trace, it then proceeds as if though the exception was were not thrown, that . That is, the future long term behavior of the application does not change based on the throwing of the exception, other than the fact that impending statements is unaffected by the exception being thrown except that any expressions or statements that occur in the try
block are skipped. Given that the resulting IOException
indicates that an operation attempted by the application failed, it is unlikely that the application will be able to operate successfully by assuming that the attempted operation succeededafter the point from which the exception is thrown are not evaluated.
Compliant Solution (Interactive)
This compliant solution attempts to recover from handles a FileNotFoundException
by forcing requesting that the user to specify another file when a particular file does not exist in the user-specific directory.name:
Code Block | ||
---|---|---|
| ||
boolean volatile validFlag = false; do { try { // ... // If requested file does not exist, throws FileNotFoundException // If requested file exists, sets a Boolean flag validFlag to true validFlag = true; } catch (FileNotFoundException e) { // Ask the user for a different filenamefile name } } while (validFlag != true); // Use the file |
The user is To comply with ERR01-J. Do not allow exceptions to expose sensitive information, the user should only be allowed to access files in only the a user-specific directory so no file system information is leaked in the process (. This prevents any other IOException
that escapes the loop from leaking sensitive file system information.
Compliant Solution (Exception Reporter)
Proper reporting of exceptional conditions is context-dependent. For example, GUI applications should report the exception in a graphical manner, such as in an error dialog box. Most library classes should be able to objectively determine how an exception should be reported to preserve modularity; they cannot rely on System.err
, on any particular logger, or on the availability of the windowing environment. As a result, library classes that wish to report exceptions should specify the API they use to report exceptions. This compliant solution specifies both an interface for reporting exceptions, which exports the report()
method, and a default exception reporter class that the library can use. The exception reporter can be overridden by subclasses.
Code Block | ||
---|---|---|
| ||
public interface Reporter {
public void report(Throwable t);
}
class ExceptionReporterPermission extends Permission {
// ...
}
public class ExceptionReporter {
// Exception reporter that prints the exception
// to the console (used as default)
private static final Reporter PrintException = new Reporter() {
public void report(Throwable t) {
System.err.println(t.toString());
}
};
// Stores the default reporter
// The default reporter can be changed by the user
private static Reporter Default = PrintException;
// Helps change the default reporter back to
// PrintException in the future
public static Reporter getPrintException() {
return PrintException;
}
public static Reporter getExceptionReporter() {
return Default;
}
// May throw a SecurityException (which is unchecked)
public static void setExceptionReporter(Reporter reporter) {
// Custom permission
ExceptionReporterPermission perm = new
ExceptionReporterPermission("exc.reporter");
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Check whether the caller has appropriate permissions
sm.checkPermission(perm);
}
// Change the default exception reporter
Default = reporter;
}
}
|
The setExceptionReporter()
method prevents hostile code from maliciously installing a more verbose reporter that leaks sensitive information or that directs exception reports to an inappropriate location, such as the attacker's computer, by limiting attempts to change the exception reporter to callers that have the custom permission ExceptionReporterPermission
with target exc.reporter
.
The library may subsequently use the exception reporter in catch
clauses:
Code Block | ||
---|---|---|
| ||
try {
// ...
} catch (IOException warning) {
ExceptionReporter.getExceptionReporter().report(warning);
// Recover from the exception...
}
|
Any client code that possesses the required permissions can override the ExceptionReporter
with a handler that logs the error or provides a dialog box, or both. For example, a GUI client using Swing may require exceptions to be reported using a dialog box:
Code Block | ||
---|---|---|
| ||
ExceptionReporter.setExceptionReporter(new ExceptionReporter() {
public void report(Throwable exception) {
JOptionPane.showMessageDialog(frame,
exception.toString,
exception.getClass().getName(),
JOptionPane.ERROR_MESSAGE);
}});
|
Compliant Solution (Subclass Exception Reporter and Filter-Sensitive Exceptions)
Sometimes exceptions must be hidden from the user for security reasons (see ERR01EXC06-J. Do not allow exceptions to transmit sensitive information).
Noncompliant Code Example
expose sensitive information). In such cases, one acceptable approach is to subclass the ExceptionReporter
class and add a filter()
method in addition to overriding the default report()
method.
Code Block | ||
---|---|---|
| ||
class MyExceptionReporter extends ExceptionReporter {
private static final Logger logger =
Logger.getLogger("com.organization.Log");
public static void report(Throwable t) {
t = filter(t);
if (t != null) {
logger.log(Level.FINEST, "Loggable exception occurred", t);
}
}
public static Exception filter(Throwable t) {
if (t instanceof SensitiveException1) {
// Too sensitive, return nothing (so that no logging happens)
return null;
} else if (t instanceof SensitiveException2) {
// Return a default insensitive exception instead
return new FilteredSensitiveException(t);
}
// ...
// Return for reporting to the user
return t;
}
}
// ...Definitions for SensitiveException1, SensitiveException2
// and FilteredSensitiveException... |
The report()
method accepts a Throwable
instance and consequently handles all errors, checked exceptions, and unchecked exceptions. The filtering mechanism is based on a whitelisting approach wherein only nonsensitive exceptions are propagated to the user. Exceptions that are forbidden to appear in a log file can be filtered in the same fashion (see FIO13-J. Do not log sensitive information outside a trust boundary). This approach provides the benefits of exception chaining by reporting exceptions tailored to the abstraction while also logging the low-level cause for future failure analysis [Bloch 2008].
Noncompliant Code Example
If a thread is interrupted while sleeping or waiting, it causes a java.lang.InterruptedException
to be thrown. However, the run()
method of interface Runnable
cannot throw a checked exception and must handle InterruptedException
. This noncompliant code example catches and suppresses InterruptedException
:It is not possible to propagate a checked exception by throwing it from a Runnable
object's run()
method. Consequently, this noncompliant code example catches java.lang.InterruptedException
but ignores it.
Code Block | ||
---|---|---|
| ||
class Foo implements Runnable { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // Ignore } } } |
Any callers higher up in the call stack are unable to determine that an interrupted exception occurred and act on it \[[Goetz 06|AA. Java References#Goetz 06]\]This code prevents callers of the Wiki Markup run()
method from determining that an interrupted exception occurred. Consequently, caller methods such as Thread.start()
cannot act on the exception [Goetz 2006]. Likewise, if this code were called in its own thread, it would prevent the calling thread from knowing that the thread was interrupted.
Compliant Solution
This compliant solution catches the InterruptedException
and restores the interrupted status by calling the interrupt()
method on the current thread. :
Code Block | ||
---|---|---|
| ||
class Foo implements Runnable { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Reset interrupted status } } } |
Consequently, code that is higher up on the call stack can see that an interrupt was issued \[[Goetz 06|AA. Java References#Goetz 06]\calling methods (or code from a calling thread) can determine that an interrupt was issued [Goetz 2006]. Wiki Markup
Exceptions
EX1: It is reasonable to ignore handling an exception that occurs within a catch
or finally
block, such as when closing a FileInputStream
object.
ERR00-J-EX0: Exceptions that occur during the freeing of a resource may be suppressed in those cases where failure to free the resource cannot affect future program behavior. Examples of freeing resources include closing files, network sockets, shutting down threads, and so forth. Such resources are often freed in catch
or finally
blocks and never reused during subsequent execution. Consequently, the exception cannot influence future program behavior through any avenue other than resource exhaustion. When resource exhaustion is adequately handled, it is sufficient to sanitize and log the exception for future improvement; additional error handling is unnecessary in this case.
ERR00-J-EX1: When recovery from an exceptional condition is impossible at a particular abstraction level, code at that level must not handle that exceptional condition. In such cases, an appropriate EX2: It is also permissible to ignore handling an exception when it is not possible to recover from the exceptional condition at that abstraction level. In such cases, the exception must be thrown so that higher level code can try recovering from catch the exceptional condition by catching and handling it. attempt recovery. The most common implementation for this case is to omit a catch
block and allow the exception to propagate normally:
Code Block | ||
---|---|---|
| ||
// When recovery is possible at higher levels private void doSomething() throws FileNotFoundException { // Requested file does not exist; throws FileNotFoundException // Higher level code can handle it by displaying a dialog box and asking // the user for the file name } |
If the higher level code is also incapable of staging a recovery, the checked exception may be wrapped in an unchecked exception and re-thrown.Some APIs may limit the permissible exceptions thrown by particular methods. In such cases, it may be necessary to catch an exception and either wrap it in a permitted exception or translate it to one of the permitted exceptions:
Code Block | ||
---|---|---|
| ||
public void myMethod() throws MyProgramException { // ... try { // Requested file does not exist // User is unable to supply the file name } catch (FileNotFoundException e) { throw new RuntimeExceptionMyProgramException(e); } |
...
|
...
// ... } |
Alternatively, when higher level code is also unable to recover from a particular exception, the checked exception may be wrapped in an unchecked exception and rethrown.
ERR00-J-EX2: An InterruptedException
may be caught and suppressed when extending class Thread
[Goetz 2006]. An interruption request may also be suppressed by code that implements a thread's interruption policy [Goetz 2006, p. 143only situation in which it is acceptable to swallow an interrupt is when you are extending Thread and therefore control all the code higher up on the call stack." \[[Goetz 06|AA. Java References#Goetz 06]\]. In such cases {{InterruptedException}} may be caught and ignored. A interruption request may also be swallowed by code that implements a thread's interruption policy \[[Goetz 06, pg 143|AA. Java References#Goetz 06]\].
Risk Assessment
Ignoring or suppressing exceptions violates the fail-safe criteria of an applicationcan result in inconsistent program state.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
ERR00-J |
Low |
Probable |
Medium | P4 | L3 |
Automated Detection
...
Detection of suppressed exceptions is straightforward. Sound determination of which specific cases represent violations of this rule and which represent permitted exceptions to the rule is infeasible. Heuristic approaches may be effective.
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| JAVA.STRUCT.EXCP.EEH | Empty Exception Handler (Java) | ||||||
Coverity | 7.5 | MISSING_THROW | Implemented | ||||||
Parasoft Jtest |
| CERT.ERR00.LGE CERT.ERR00.UCATCH | Ensure all exceptions are either logged with a standard logger or rethrown Use a caught exception in the "catch" block | ||||||
PVS-Studio |
| V5301 | |||||||
SonarQube |
| S1166 | Exception handlers should preserve the original exceptions |
Related Vulnerabilities
References
Wiki Markup |
---|
\[[JLS 05|AA. Java References#JLS 05]\] [Chapter 11, Exceptions|http://java.sun.com/docs/books/jls/third_edition/html/exceptions.html]
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 65: "Don't ignore exceptions", Item 62: "Document all exceptions thrown by each method"
\[[Goetz 06|AA. Java References#Goetz 06]\] 5.4 Blocking and interruptible methods
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 390|http://cwe.mitre.org/data/definitions/390.html] "Detection of Error Condition Without Action" |
describes a vulnerability in the ActiveMQ service. When ActiveMQ receives an invalid username and password from a Stomp client, a security exception is generated but is subsequently ignored, leaving the client connected with full and unrestricted access to ActiveMQ.
Related Guidelines
Bibliography
Item 62, "Document All Exceptions Thrown by Each Method" | |
Section 5.4, "Blocking and Interruptible Methods" | |
[JLS 2015] |
...
17. Exceptional Behavior (EXC) 17. Exceptional Behavior (EXC) EXC01-J. Use a class dedicated to reporting exceptions