Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e174ca6

Browse files
committed
Query for uncaught NumberFormatException
1 parent 1f390f2 commit e174ca6

3 files changed

Lines changed: 141 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
String s = ...;
2+
int n;
3+
4+
n = Integer.parseInt(s); // BAD: NumberFormatException is not caught.
5+
6+
try {
7+
n = Integer.parseInt(s);
8+
} catch (NumberFormatException e) { // GOOD: The exception is caught.
9+
// Handle the exception
10+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
7+
<overview>
8+
<p>Method such as <code>Integer.parseInt</code> that parse strings into numbers
9+
throw
10+
<code>NumberFormatException</code> if the its argument cannot be parsed.
11+
This exception should be caught so that any parse errors can be handled.
12+
</p>
13+
14+
</overview>
15+
<recommendation>
16+
17+
<p>It is usually best to handle <code>NumberFormatException</code> in a <code>catch</code> clause
18+
surrounding the call to the parsing method.</p>
19+
20+
</recommendation>
21+
<example>
22+
23+
<p>In the following example, the first call to <code>Integer.parseInt</code> does not catch the exception.
24+
The second call does.
25+
</p>
26+
27+
<sample src="NumberFormatException.java" />
28+
29+
</example>
30+
<references>
31+
32+
33+
<li>
34+
Java Platform, Standard Edition 6, API Specification:
35+
<a href="http://docs.oracle.com/javase/6/docs/api/java/lang/Integer.html#valueOf(java.lang.String)">Integer.valueOf</a>,
36+
<a href="http://docs.oracle.com/javase/6/docs/api/java/lang/Integer.html#parseInt(java.lang.String)">Integer.parseInt</a>,
37+
<a href="http://docs.oracle.com/javase/6/docs/api/java/lang/Long.html#parseLong(java.lang.String)">Long.parseLong</a>,
38+
<a href="http://docs.oracle.com/javase/6/docs/api/java/lang/NumberFormatException.html">NumberFormatException</a>.
39+
</li>
40+
41+
42+
</references>
43+
</qhelp>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* @name Missing catch of NumberFormatException
3+
* @description Calling 'Integer.parseInt' without handling 'NumberFormatException'.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @precision high
7+
* @id java/uncaught-number-format-exception
8+
* @tags reliability
9+
* external/cwe/cwe-248
10+
*/
11+
import java
12+
13+
private class SpecialMethodAccess extends MethodAccess {
14+
predicate isValueOfMethod(string klass) {
15+
this.getMethod().getName() = "valueOf" and
16+
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) and
17+
this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String")
18+
}
19+
20+
predicate isParseMethod(string klass, string name) {
21+
this.getMethod().getName() = name and
22+
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass)
23+
}
24+
25+
predicate throwsNFE() {
26+
this.isParseMethod("Byte", "parseByte") or
27+
this.isParseMethod("Short", "parseShort") or
28+
this.isParseMethod("Integer", "parseInt") or
29+
this.isParseMethod("Long", "parseLong") or
30+
this.isParseMethod("Float", "parseFloat") or
31+
this.isParseMethod("Double", "parseDouble") or
32+
this.isParseMethod("Byte", "decode") or
33+
this.isParseMethod("Short", "decode") or
34+
this.isParseMethod("Integer", "decode") or
35+
this.isParseMethod("Long", "decode") or
36+
this.isValueOfMethod("Byte") or
37+
this.isValueOfMethod("Short") or
38+
this.isValueOfMethod("Integer") or
39+
this.isValueOfMethod("Long") or
40+
this.isValueOfMethod("Float") or
41+
this.isValueOfMethod("Double")
42+
}
43+
}
44+
45+
private class SpecialClassInstanceExpr extends ClassInstanceExpr {
46+
predicate isStringConstructor(string klass) {
47+
cie.getType().(RefType).hasQualifiedName("java.lang", klass) and
48+
cie.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String") and
49+
cie.getNumberOfParameters() = 1
50+
}
51+
52+
predicate throwsNFE() {
53+
this.isStringConstructor("Byte") or
54+
this.isStringConstructor("Short") or
55+
this.isStringConstructor("Integer") or
56+
this.isStringConstructor("Long") or
57+
this.isStringConstructor("Float") or
58+
this.isStringConstructor("Double")
59+
}
60+
}
61+
62+
private predicate catchesNFE(TryStmt t) {
63+
exists(CatchClause cc, LocalVariableDeclExpr v |
64+
t.getACatchClause() = cc and
65+
cc.getVariable() = v and
66+
v.getType().(RefType).getASubtype*().hasQualifiedName("java.lang", "NumberFormatException")
67+
)
68+
}
69+
70+
private predicate throwsNFE(Expr e) {
71+
e.(SpecialClassInstanceExpr).throwsNFE() or e.(SpecialMethodAccess).throwsNFE()
72+
}
73+
74+
from Expr e
75+
where
76+
throwsNFE(e) and
77+
not exists(TryStmt t |
78+
t.getBlock() = e.getEnclosingStmt().getParent*() and
79+
catchesNFE(t)
80+
) and
81+
not exists(Callable c |
82+
e.getEnclosingCallable() = c and
83+
c.getAThrownExceptionType().getASubtype*().hasQualifiedName("java.lang", "NumberFormatException")
84+
)
85+
select
86+
e, "Potential uncaught 'java.lang.NumberFormatException'."
87+
88+

0 commit comments

Comments
 (0)