Programs must not catch java.lang.NullPointerException
. A NullPointerException
exception thrown at runtime indicates the existence of an underlying null
pointer dereference that must be fixed in the application code (see EXP01-J. Do not use a null in a case where an object is required for more information). Handling the underlying null pointer dereference by catching the NullPointerException
rather than fixing the underlying problem is inappropriate for several reasons. First, catching NullPointerException
adds significantly more performance overhead than simply adding the necessary null checks [Bloch 2008]. Second, when multiple expressions in a try
block are capable of throwing a NullPointerException
, it is difficult or impossible to determine which expression is responsible for the exception because the NullPointerException
catch
block handles any NullPointerException
thrown from any location in the try
block. Third, programs rarely remain in an expected and usable state after a NullPointerException
has been thrown. Attempts to continue execution after first catching and logging (or worse, suppressing) the exception rarely succeed.
Likewise, programs must not catch RuntimeException
, 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 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 |
Few, if any, methods are capable of handling all possible runtime exceptions. Consequently, methods are forbidden to catch RuntimeException
. When a method catches RuntimeException
, it may receive exceptions unanticipated by the designer, such as NullPointerException
. Many catch
clauses simply log or ignore the enclosed exceptional condition, and attempt to resume normal execution; this practice often violates guideline 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. Additionally, methods must not catch Exception
or Throwable
, because this implies catching RuntimeException
; RuntimeException
extends Exception
which in turn extends Throwable
. Finally, any class that catches RuntimeException
also violates ERR15-J. Do not catch NullPointerException.
Noncompliant Code Example
This noncompliant code example accepts a String
argument and attempts to determine whether it consists of a capital letter succeeded by lowercase letters. To handle anticipated corner cases, it wraps the code in a try-catch
block and reports any runtime exceptions that arise.
Code Block | ||
---|---|---|
| ||
boolean isCapitalized(String s) {
try {
if (s.equals("")) {
return true;
}
String first = s.substring( 0, 1);
String rest = s.substring( 1);
return (first.equals (first.toUpperCase()) &&
rest.equals (rest.toLowerCase()));
} catch (RuntimeException exception) {
ExceptionReporter.report(exception);
}
return false;
}
|
This code reports a null pointer exception condition when s
is a null pointer, as intended by the programmer. However, it also unintentionally catches other exceptions that the programmer failed to anticipate, such as an ArrayIndexOutOfBoundsException
resulting from an out of bounds index. These other exceptions are reported, but are unlikely to be handled properly.
Compliant Solution
This compliant solution avoids catching RuntimeException
. Instead, it catches only the exceptions intended by the programmer; all other exceptions propagate up the call stack, to be handled by appropriate higher-level catch blocks.
Code Block | ||
---|---|---|
| ||
boolean isCapitalized(String s) { try { String ifnames[] = (s.equalssplit(" ")) ; if (names.length != 2) { return truefalse; } String first = s.substring(0, 1return (isCapitalized(names[0]) && isCapitalized(names[1])); } catch String rest = s.substring(1); return (first.equals (first.toUpperCase()) && rest.equals (rest.toLowerCase())); } catch (NullPointerException exception) { (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) { ExceptionReporter.report (exception); } return false; } |
Noncompliant Code Example
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 dangerous, 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, catching Exception
also catches unchecked exceptions; the developer has failed to anticipate this possibility.
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.
Code Block | ||
---|---|---|
| ||
try {
division(200, 5);
division(200, 0); // Divide by zero
} catch (ArithmeticException ae) {
throw new DivideByZeroException();
} catch (Exception e) {
System.out.println("Exception occurred :" + e.getMessage());
}
|
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.
}
String names[] = s.split(" ");
if (names.length != 2) {
return false;
}
return (isCapitalized(names[0]) && isCapitalized(names[1]));
} |
Compliant Solution
This compliant solution omits an explicit check for a null reference and permits a NullPointerException
to be thrown:
Code Block | ||
---|---|---|
| ||
boolean isName(String s) /* Throws NullPointerException */ {
String names[] = s.split(" ");
if (names.length != 2) {
return false;
}
return (isCapitalized(names[0]) && isCapitalized(names[1]));
} |
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 method 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 (Null Object Pattern)
This noncompliant code example is derived from the logging service Null Object design pattern described by Henney [Henney 2003]. 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.
Code Block | ||
---|---|---|
| ||
public interface Log {
void write(String messageToLog);
}
public class FileLog implements Log {
private final FileWriter out;
FileLog(String logFileName) throws IOException {
out = new FileWriter(logFileName, true);
}
public void write(String messageToLog) {
// Write message to file
}
}
public class ConsoleLog implements Log {
public void write(String messageToLog) {
System.out.println(messageToLog); // Write message to console
}
}
class Service {
private Log log;
Service() {
this.log = null; // No logger
}
Service(Log log) {
this.log = log; // Set the specified logger
}
public void handle() {
try {
log.write("Request received and handled"); | ||
Code Block | ||
| ||
import java.io.IOException; public class DivideException { public static void main(String[] args) { try { division(200,5); division(200,0); // Divide by zero } catch (ArithmeticException ae) { throw new DivideByZeroException(); // DivideByZeroException extends Exception so is checked } catch (IOExceptionNullPointerException ienpe) { ExceptionReporter.report(ex);// Ignore } } public static void divisionmain(int totalSum, int totalNumberString[] args) throws ArithmeticException, IOException { intService averages = totalSumnew / totalNumber; Service(new FileLog("logfile.log")); // Additional operations that may throw IOException...s.handle(); s = new Service(new ConsoleLog()); Systems.out.println("Average: "+ average); handle(); } } |
Note that DivideByZeroException
is a custom exception type that extends Exception
.
Each Service
object must support the possibility that a Log
object may be null
because clients may choose not to perform logging. This noncompliant code example eliminates null checks by using a try-catch
block that ignores NullPointerException
.
This design choice suppresses genuine occurrences of NullPointerException
in violation of The ExceptionReporter
class is documented in ERR00-J. Do not suppress or ignore checked exceptions.
Compliant Solution (Java 1.7)
It also violates the design principle that exceptions should be used only for exceptional conditions because ignoring a null Log
object is part of the ordinary operation of 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.
This compliant solution modifies the no-argument constructor of class Service
to use the do-nothing behavior provided by an additional class, Log.NULL
; it leaves the other classes unchangedJava 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 up the call stack.
Code Block | ||
---|---|---|
| ||
import java.io.IOException; public classinterface DivideExceptionLog { public static final void main(String[] args) { try Log NULL = new Log() { public void division(200,5); write(String messageToLog) { division(200,0); // DivideDo bynothing zero } }; void write(String messageToLog); } class catch (ArithmeticException|IOException ex) { Service { private final Log log; ExceptionReporter.reportService(ex);{ } this.log = Log.NULL; } 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); } } |
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 out sensitive information from exceptions before the call stack leaves a trust boundary. Refer to guideline 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
.
Wiki Markup |
---|
*EXC14-EX1*: Task processing threads such as worker threads in a thread pool or the swing event dispatch thread are permitted to catch {{RuntimeException}} when they call untrusted code through an abstraction such as {{Runnable}} \[[Goetz 2006 pg 161|AA. Bibliography#Goetz 06]\]. |
EXC14-EX2: Systems that require substantial fault tolerance or graceful degradation are permitted to catch and log general exceptions such as Throwable
at appropriate levels of abstraction. For example:
- A realtime control system that catches and logs all exceptions at the outermost layer, followed by warm-starting the system so that realtime 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 RuntimeException
traps several types of exceptions not intended to be caught. This prevents them from being handled properly.
Guideline | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXC14-J | low | likely | medium | P6 | L2 |
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 guideline is infeasible. Heuristic techniques may be helpful.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Bibliography
Wiki Markup |
---|
\[[Doshi 2003|AA. Bibliography#Doshi 03]\]
\[[JLS 2005|AA. Bibliography#JLS 05]\] [Chapter 11, Exceptions|http://java.sun.com/docs/books/jls/third_edition/html/exceptions.html]
\[[J2SE 2011|AA. Bibliography#J2SE 11]\] Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking
\[[MITRE 2009|AA. Bibliography#MITRE 09]\] [CWE ID 396|http://cwe.mitre.org/data/definitions/396.html] "Declaration of Catch for Generic Exception", [CWE ID 7|http://cwe.mitre.org/data/definitions/7.html] "J2EE Misconfiguration: Missing Error Handling", [CWE ID 537|http://cwe.mitre.org/data/definitions/537.html] "Information Leak Through Java Runtime Error Message", [CWE ID 536|http://cwe.mitre.org/data/definitions/536.html] "Information Leak Through Servlet Runtime Error Message"
\[[Muller 2002|AA. Bibliography#Muller 02]\]
\[[Rogue 2000|AA. Bibliography#Rogue 2000]\] Rule 87: Do not silently absorb a run-time or error exception
\[[Schweisguth 2003|AA. Bibliography#Schweisguth 03]\]
\[[Tutorials 2008|AA. Bibliography#tutorials 08]\] Exceptions|http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html] |
// ...
} |
Declaring the log
reference final ensures that its value is assigned during initialization.
An acceptable alternative implementation uses accessor methods to control all interaction with the reference to the current log. The accessor method to set a log ensures use of the null object in place of a null reference. The accessor method to get a log ensures that any retrieved instance is either an actual logger or a null object (but never a null reference). Instances of the null object are immutable and are inherently thread-safe.
Some system designs require returning a value from a method rather than implementing do-nothing behavior. One acceptable approach is use of an exceptional value object that throws an exception before the method returns [Cunningham 1995]. This approach can be a useful alternative to returning null
.
In distributed environments, the null object must be passed by copy to ensure that remote systems avoid the overhead of a remote call argument evaluation on every access to the null object. Null object code for distributed environments must also implement the Serializable
interface.
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)
This noncompliant code example assumes that the original version of the division()
method was declared to throw only ArithmeticException
. However, the caller catches the more general Exception
type to report arithmetic problems rather than catching the specific exception ArithmeticException
type. This practice is risky because future changes to the method signature could add more exceptions to the list of potential exceptions the caller must handle. In this example, a revision of the division()
method can throw IOException
in addition to ArithmeticException
. However, the compiler will not diagnose the lack of a corresponding handler because the invoking method already catches IOException
as a result of catching Exception
. Consequently, the recovery process might 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 division(int totalSum, int totalNumber)
throws ArithmeticException, IOException {
int average = totalSum / totalNumber;
// Additional operations that may throw IOException...
System.out.println("Average: " + average);
}
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());
}
}
} |
Noncompliant Code Example
This noncompliant code example attempts to solve the problem by specifically catching ArithmeticException
. However, it continues to catch Exception
and consequently catches both unanticipated checked exceptions and unanticipated runtime exceptions.
Code Block | ||
---|---|---|
| ||
try {
division(200, 5);
division(200, 0); // Divide by zero
} catch (ArithmeticException ae) {
throw new DivideByZeroException();
} catch (Exception e) {
System.out.println("Exception occurred :" + e.getMessage());
} |
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.
Code Block | ||
---|---|---|
| ||
import java.io.IOException;
public class DivideException {
public static void main(String[] args) {
try {
division(200, 5);
division(200, 0); // Divide by zero
} catch (ArithmeticException ae) {
// DivideByZeroException extends Exception so is checked
throw new DivideByZeroException();
} catch (IOException ex) {
ExceptionReporter.report(ex);
}
}
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);
}
} |
The ExceptionReporter
class is documented in ERR00-J. Do not suppress or ignore checked exceptions.
Compliant Solution (Java SE 7)
Java SE 7 allows a single catch
block to catch multiple 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 catch
clause of a try
statement on the stack.
Code Block | ||
---|---|---|
| ||
import java.io.IOException;
public class DivideException {
public static void main(String[] args) {
try {
division(200, 5);
division(200, 0); // Divide by zero
} catch (ArithmeticException | IOException ex) {
ExceptionReporter.report(ex);
}
}
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);
}
} |
Exceptions
ERR08-J-EX0: A catch
block may catch all exceptions to process them before rethrowing them (filtering sensitive information from exceptions before the call stack leaves a trust boundary, for example). Refer to ERR01-J. Do not allow exceptions to expose sensitive information and weaknesses CWE 7 and CWE 388 for more information. In such cases, a catch
block should catch Throwable
rather than Exception
or RuntimeException
.
This code sample catches all exceptions and wraps them in a custom DoSomethingException
before rethrowing them:
Code Block | ||
---|---|---|
| ||
class DoSomethingException extends Exception {
public DoSomethingException(Throwable cause) {
super(cause);
}
// Other methods
};
private void doSomething() throws DoSomethingException {
try {
// Code that might throw an Exception
} catch (Throwable t) {
throw new DoSomethingException(t);
}
} |
Exception wrapping is a common technique to safely handle unknown exceptions. For another example, see ERR06-J. Do not throw undeclared checked exceptions.
ERR08-J-EX1: Task processing threads such as worker threads in a thread pool or the Swing event dispatch thread are permitted to catch RuntimeException
when they call untrusted code through an abstraction such as the Runnable
interface [Goetz 2006, p. 161].
ERR08-J-EX2: Systems that require substantial fault tolerance or graceful degradation are permitted to catch and log general exceptions such as Throwable
at appropriate levels of abstraction. For example:
- 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
, Exception
, or Throwable
may unintentionally trap other exception types and prevent them from being handled properly.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR08-J | Medium | Likely | Medium | P12 | L1 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| JAVA.STRUCT.EXCP.GEH | Generic Exception Handler (Java) | ||||||
Parasoft Jtest |
| CERT.ERR08.NCNPE | Do not catch 'NullPointerException' | ||||||
SonarQube |
| ||||||||
SpotBugs |
| DCN_NULLPOINTER_EXCEPTION | Implemented (since 4.5.0) |
...
ERR13-J. Do not throw RuntimeException 06. Exceptional Behavior (ERR) ERR15-J. Do not catch NullPointerException