You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 70 Next »

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. Methods are also forbidden to catch Exception or Throwable, because this implies catching RuntimeException; RuntimeException extends Exception which in turn extends Throwable.

Finally, any class that catches RuntimeException also automatically 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.

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.

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 (NullPointerException exception) {
    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.

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.

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.

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 (IOException ie) { 
      System.out.println("I/O Exception occurred :" + ie.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);   	
  }
}

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:

In such cases, a catch block should catch Throwable rather than Exception or RuntimeException.

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]].

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

[[Doshi 2003]]
[[JLS 2005]] Chapter 11, Exceptions
[[MITRE 2009]] CWE ID 396 "Declaration of Catch for Generic Exception", CWE ID 7 "J2EE Misconfiguration: Missing Error Handling", CWE ID 537 "Information Leak Through Java Runtime Error Message", CWE ID 536 "Information Leak Through Servlet Runtime Error Message"
[[Muller 2002]]
[[Rogue 2000]] Rule 87: Do not silently absorb a run-time or error exception
[[Schweisguth 2003]]
[[Tutorials 2008]] Exceptions|http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html]


ERR13-J. Do not throw RuntimeException      06. Exceptional Behavior (ERR)      ERR15-J. Do not catch NullPointerException

  • No labels