A method should never throw RuntimeException
or Exception
. This is because handling these requires catching RuntimeException
, which is forbidden in [EXC32-J. Catch specific exceptions as opposed to the more general RuntimeException]. Moreover, throwing a RuntimeException
can lead to subtle errors such as a caller who fails to retrieve a return value from an offending method, is unable to check for appropriate feedback. The Java Language Specification (Section 8.4.7 Method Body) allows the declaration of a method with a return type without making it necessary to return a value if a runtime exception is thrown from within the method [[JLS 05]].
Instead, always throw an exception subclassed from Exception
. It is permissible to construct an exception class specifically for a single throw
statement.
Noncompliant Code Example
The following function takes a string and returns true
if it consists of a capital letter followed by lowercase letters. To handle corner cases, it checks for the conditions and throws exceptions if they are likely to prevent normal analysis.
boolean isCapitalized(String s) { if (s == null) { throw new RuntimeException("Null String"); } 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())); }
To handle the case of passing in a null
string parameter, code calling this function may require catching RuntimeException
, which is a violation of EXC32-J. Catch specific exceptions as opposed to the more general RuntimeException.
Compliant Solution
An exception specifically devoted to the error is more appropriate.
boolean isCapitalized(String s) { if (s == null) { throw new NullPointerException(); } 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())); }
Noncompliant Code Example
This noncompliant code snippet uses a broad Exception
class in the throws
declaration of the method.
private void doSomething() throws Exception { //... }
Compliant Solution
To be compliant, be as specific as possible when declaring exceptions and respect the required abstraction level.
private void doSomething() throws IOException { //... }
Risk Assessment
Throwing RuntimeException
, Exception
prevents classes from catching the intended exception without catching other unintended exceptions as well.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
EXC33- J |
low |
likely |
medium |
P6 |
L2 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[MITRE 09]] CWE ID 397 "Declaration of Throws for Generic Exception", CWE ID 537 "Information Leak Through Java Runtime Error Message"
[[Goetz 04b]]
[[Tutorials 08]] Unchecked Exceptions â” The Controversy
EXC32-J. Catch specific exceptions as opposed to the more general RuntimeException 13. Exceptional Behavior (EXC) 13. Serialization (SER)