...
Likewise, programs must not catch RuntimeException
, or its ancestors Exception
or Throwable
. Few, if any, methods are capable of handling all possible runtime exceptions. When a method catches RuntimeException
, it may receive exceptions unanticipated by the designer, including NullPointerException
and ArrayIndexOutOfBoundsException
. Many catch
clauses simply log or ignore the enclosed exceptional condition, and attempt to resume normal execution; this practice often violates rule ERR00-J. Do not suppress or ignore checked exceptions. Runtime exceptions often indicate bugs in the program that should be fixed by the developer, and often cause control flow vulnerabilities.
Noncompliant Code Example (NullPointerException
)
This noncompliant code example defines an isName()
method that takes a String
argument and returns true
if the given string is a valid name. A valid name is defined as two capitalized words separated by one or more spaces. Rather than checking to see whether the given string is null
, the method catches NullPointerException
and returns false
.
Code Block | ||
---|---|---|
| ||
boolean isName(String s) { try { String names[] = s.split(" "); if (names.length != 2) { return false; } return (isCapitalized(names[0]) && isCapitalized(names[1])); } catch (NullPointerException e) { return false; } } |
Compliant Solution
This compliant solution explicitly checks the String
argument for null
rather than catching NullPointerException
.
Code Block | ||
---|---|---|
| ||
boolean isName(String s) { if (s == null) { return false; } String names[] = s.split(" "); if (names.length != 2) { return false; } return (isCapitalized(names[0]) && isCapitalized(names[1])); } |
Compliant Solution
This compliant solution performs no null check and permits a NullPointerException
to be thrown.
...
Omitting the null check means that the program fails more quickly than if the program had returned false and lets an invoking method discover the null value. A function that throws a NullPointerException
without a null check must provide a precondition that the argument being passed to it is not null.
Noncompliant Code Example (Explicit Null Checks)
Wiki Markup |
---|
This noncompliant code example is derived from the logging service null object design pattern described by Henney \[[Henney 2003|AA. Bibliography#Henney 03]\]. The logging service is composed of two classes: one that prints the triggering activity's details to a disk file using the {{FileLog}} class, and another that prints to the console using the {{ConsoleLog}} class. An interface, {{Log}}, defines a {{write()}} method that is implemented by the respective log classes. Method selection occurs polymorphically at runtime. The logging infrastructure is subsequently used by a {{Service}} class. |
...
This design choice suppresses genuine occurrences of NullPointerException
. It also violates the design principle that exceptions should be used only for exceptional conditions; ignoring a null
Log
object is part of ordinary operation for a server.
Compliant Solution (Null Object Pattern)
The null object design pattern provides an alternative to the use of explicit null
checks in code. It reduces the need for explicit null
checks through the use of an explicit, safe null object rather than a null
reference.
...
Code that uses this pattern must be clearly documented to ensure that security critical messages are never discarded because the pattern has been misapplied.
Noncompliant Code Example (Division)
In this noncompliant code example, the original version of the division()
method was declared to throw only ArithmeticException
. However, the caller catches a more general type (Exception
) to report arithmetic problems, rather than catching the specific exception type (ArithmeticException
). This practice is insecure, because future changes to the method signature could add to the list of potential exceptions the caller must handle. In this example, a newer version of the division
method can potentially throw IOException
in addition to ArithmeticException
. However, the compiler cannot tell the caller's developer that he must provide a corresponding handler, because his existing code already catches IOException
as a result of catching Exception
. Consequently, the recovery process may be inappropriate for the specific exception type that is thrown. Furthermore, the developer has failed to anticipate that catching Exception
also catches unchecked exceptions.
Code Block | ||
---|---|---|
| ||
public class DivideException { public static void main(String[] args) { try { division(200, 5); division(200, 0); // Divide by zero } catch (Exception e) { System.out.println("Divide by zero exception : " + e.getMessage()); } } public static void division(int totalSum, int totalNumber) throws ArithmeticException, IOException { int average = totalSum / totalNumber; // Additional operations that may throw IOException... System.out.println("Average: " + average); } } |
Noncompliant Code Example
This noncompliant code example attempts improvement by specifically catching ArithmeticException
. However, it continues to catch Exception
, and consequently catches both unanticipated checked exceptions and also unanticipated runtime exceptions.
...
Note that DivideByZeroException
is a custom exception type that extends Exception
.
Compliant Solution
This compliant solution catches only the specific anticipated exceptions (ArithmeticException
and IOException
). All other exceptions are permitted to propagate up the call stack.
...
The ExceptionReporter
class is documented in ERR00-J. Do not suppress or ignore checked exceptions.
Compliant Solution (Java 1.7)
Java 1.7 allows a single catch block to catch multiple exceptions. This allows one catch block to handle exceptions of different types, which prevents redundant code. This compliant solution catches the specific anticipated exceptions (ArithmeticException
and IOException
), and handles them with one catch clause. All other exceptions are permitted to propagate to the next nearest dynamically-enclosing catch
clause of a try
statement.
...
Note that DivideByZeroException
is a custom exception type that extends Exception
.
Exceptions
EXC14-EX0: A catch block may catch all exceptions to process them before re-throwing them. For example, filtering sensitive information from exceptions before the call stack leaves a trust boundary. Refer to rule ERR06-J. Do not allow exceptions to expose sensitive information, as well as CWE 7 and CWE 388). In such cases, a catch block should catch Throwable
rather than Exception
or RuntimeException
.
...
- A real time control system that catches and logs all exceptions at the outermost layer, followed by warm-starting the system so that real time control can continue. Such approaches are clearly justified when program termination would have safety-critical or mission-critical consequences.
- A system that catches all exceptions that propagate out of each major subsystem, logs the exceptions for later debugging, and subsequently shuts down the failing subsystem (perhaps replacing it with a much simpler, limited-functionality version) while continuing other services.
Risk Assessment
Catching NullPointerException
may mask an underlying null
dereference, degrade application performance, and result in code that is hard to understand and maintain. Likewise, catching RuntimeException
may unintentionally trap other exception types and prevent them from being handled properly.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR14-J | medium | likely | medium | P12 | L3 |
Automated Detection
Automated detection of code that catches RuntimeException
, Exception
, or Throwable
is trivial. Sound automated determination of whether such code complies with the exceptions to this rule is infeasible. Heuristic techniques may be helpful.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
MITRE CWE: | CWE ID 230 "Improper Handling of Missing Values" |
| CWE ID 232 "Improper Handling of Undefined Values" |
| CWE ID 690 "Unchecked Return Value to NULL Pointer Dereference" |
| CWE ID 395 "Use of NullPointerException Catch to Detect NULL Pointer Dereference" |
CWE ID 396 "Declaration of Catch for Generic Exception" | |
| CWE ID 7 "J2EE Misconfiguration: Missing Custom Error Page" |
| CWE ID 537 "Information Exposure Through Java Runtime Error Message" |
| CWE ID 536 "Information Exposure Through Servlet Runtime Error Message" |
The Elements of Java Style: | Rule 87: Do not silently absorb a run-time or error exception |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6f7aedd15d14322d-6c286153-44594733-b113a29d-14e72e6c68aa795675d99704"><ac:plain-text-body><![CDATA[ | [[Cunningham 1995 | AA. Bibliography#Cunningham 95]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="d68a7240d52c6e5c-348a0426-434546c6-a81db433-83bae3af2c8f70e97583765e"><ac:plain-text-body><![CDATA[ | [[Doshi 2003 | AA. Bibliography#Doshi 03]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="0ea6ba1880e6efd7-ebb240d0-46f34841-a2f5aba9-32f5e8c4201570766664b4e3"><ac:plain-text-body><![CDATA[ | [[Grand 2002 | AA. Bibliography#Grand 02]] | Chapter 8, Behavioral patterns, the Null Object | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="71043a28edcf5a4d-b3e6107d-492c4d77-ae5eaf71-3f8123ed4b5fde8397e8620f"><ac:plain-text-body><![CDATA[ | [[Henney 2003 | AA. Bibliography#Henney 03]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="16a7454e0eafd3cc-9f1ebba6-4b6242b7-8d5c87ef-348c2fb9e9e628ffeed8740e"><ac:plain-text-body><![CDATA[ | [[JLS 2005 | AA. Bibliography#JLS 05]] | [Chapter 11, Exceptions | http://java.sun.com/docs/books/jls/third_edition/html/exceptions.html] | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="b5e818b1894f2767-4253447c-49f44697-a7a0a806-356f0826c2728302d4ae5a15"><ac:plain-text-body><![CDATA[ | [[J2SE 2011 | AA. Bibliography#J2SE 11]] | Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f110a14fb9c8e173-66c847fb-47304750-ae6f8c77-1c5f6817ad7cf244110e6049"><ac:plain-text-body><![CDATA[ | [[Muller 2002 | AA. Bibliography#Muller 02]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="050d679423276bdc-e3ea9e2c-48174500-abee992d-aca679267766520779188d94"><ac:plain-text-body><![CDATA[ | [[Schweisguth 2003 | AA. Bibliography#Schweisguth 03]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="2d3d39dad1137d63-c4185f24-49ef40a4-83a0b6da-8598e51f1ee138d832d25154"><ac:plain-text-body><![CDATA[ | [[Tutorials 2008 | AA. Bibliography#tutorials 08]] | [Exceptions | http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html] | ]]></ac:plain-text-body></ac:structured-macro> |
...