Skip to content

Commit 450ff26

Browse files
committed
Convert the query to a library
1 parent 2f20486 commit 450ff26

File tree

2 files changed

+84
-65
lines changed

2 files changed

+84
-65
lines changed

java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,71 +11,7 @@
1111
*/
1212

1313
import java
14-
15-
private class SpecialMethodAccess extends MethodAccess {
16-
predicate isValueOfMethod(string klass) {
17-
this.getMethod().getName() = "valueOf" and
18-
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) and
19-
this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String")
20-
}
21-
22-
predicate isParseMethod(string klass, string name) {
23-
this.getMethod().getName() = name and
24-
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass)
25-
}
26-
27-
predicate throwsNFE() {
28-
this.isParseMethod("Byte", "parseByte") or
29-
this.isParseMethod("Short", "parseShort") or
30-
this.isParseMethod("Integer", "parseInt") or
31-
this.isParseMethod("Long", "parseLong") or
32-
this.isParseMethod("Float", "parseFloat") or
33-
this.isParseMethod("Double", "parseDouble") or
34-
this.isParseMethod("Byte", "decode") or
35-
this.isParseMethod("Short", "decode") or
36-
this.isParseMethod("Integer", "decode") or
37-
this.isParseMethod("Long", "decode") or
38-
this.isValueOfMethod("Byte") or
39-
this.isValueOfMethod("Short") or
40-
this.isValueOfMethod("Integer") or
41-
this.isValueOfMethod("Long") or
42-
this.isValueOfMethod("Float") or
43-
this.isValueOfMethod("Double")
44-
}
45-
}
46-
47-
private class SpecialClassInstanceExpr extends ClassInstanceExpr {
48-
predicate isStringConstructor(string klass) {
49-
this.getType().(RefType).hasQualifiedName("java.lang", klass) and
50-
this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String") and
51-
this.getNumArgument() = 1
52-
}
53-
54-
predicate throwsNFE() {
55-
this.isStringConstructor("Byte") or
56-
this.isStringConstructor("Short") or
57-
this.isStringConstructor("Integer") or
58-
this.isStringConstructor("Long") or
59-
this.isStringConstructor("Float") or
60-
this.isStringConstructor("Double")
61-
}
62-
}
63-
64-
class NumberFormatException extends RefType {
65-
NumberFormatException() { this.hasQualifiedName("java.lang", "NumberFormatException") }
66-
}
67-
68-
private predicate catchesNFE(TryStmt t) {
69-
exists(CatchClause cc, LocalVariableDeclExpr v |
70-
t.getACatchClause() = cc and
71-
cc.getVariable() = v and
72-
v.getType().(RefType).getASubtype*() instanceof NumberFormatException
73-
)
74-
}
75-
76-
private predicate throwsNFE(Expr e) {
77-
e.(SpecialClassInstanceExpr).throwsNFE() or e.(SpecialMethodAccess).throwsNFE()
78-
}
14+
import semmle.code.java.NumberFormatException
7915

8016
from Expr e
8117
where
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* @name Missing catch of NumberFormatException
3+
* @description Calling a string to number conversion method without handling
4+
* 'NumberFormatException' may cause unexpected runtime exceptions.
5+
* @kind problem
6+
* @problem.severity recommendation
7+
* @precision high
8+
* @id java/uncaught-number-format-exception
9+
* @tags reliability
10+
* external/cwe/cwe-248
11+
*/
12+
13+
import java
14+
15+
/** Calls a string to number conversion */
16+
private class SpecialMethodAccess extends MethodAccess {
17+
predicate isValueOfMethod(string klass) {
18+
this.getMethod().getName() = "valueOf" and
19+
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) and
20+
this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String")
21+
}
22+
23+
predicate isParseMethod(string klass, string name) {
24+
this.getMethod().getName() = name and
25+
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass)
26+
}
27+
28+
predicate throwsNFE() {
29+
this.isParseMethod("Byte", "parseByte") or
30+
this.isParseMethod("Short", "parseShort") or
31+
this.isParseMethod("Integer", "parseInt") or
32+
this.isParseMethod("Long", "parseLong") or
33+
this.isParseMethod("Float", "parseFloat") or
34+
this.isParseMethod("Double", "parseDouble") or
35+
this.isParseMethod("Byte", "decode") or
36+
this.isParseMethod("Short", "decode") or
37+
this.isParseMethod("Integer", "decode") or
38+
this.isParseMethod("Long", "decode") or
39+
this.isValueOfMethod("Byte") or
40+
this.isValueOfMethod("Short") or
41+
this.isValueOfMethod("Integer") or
42+
this.isValueOfMethod("Long") or
43+
this.isValueOfMethod("Float") or
44+
this.isValueOfMethod("Double")
45+
}
46+
}
47+
48+
/** Constructs a number from its string representation */
49+
private class SpecialClassInstanceExpr extends ClassInstanceExpr {
50+
predicate isStringConstructor(string klass) {
51+
this.getType().(RefType).hasQualifiedName("java.lang", klass) and
52+
this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String") and
53+
this.getNumArgument() = 1
54+
}
55+
56+
predicate throwsNFE() {
57+
this.isStringConstructor("Byte") or
58+
this.isStringConstructor("Short") or
59+
this.isStringConstructor("Integer") or
60+
this.isStringConstructor("Long") or
61+
this.isStringConstructor("Float") or
62+
this.isStringConstructor("Double")
63+
}
64+
}
65+
66+
/** The class `java.lang.NumberFormatException` */
67+
class NumberFormatException extends RefType {
68+
NumberFormatException() { this.hasQualifiedName("java.lang", "NumberFormatException") }
69+
}
70+
71+
/** Holds if NFE is caught */
72+
predicate catchesNFE(TryStmt t) {
73+
exists(CatchClause cc, LocalVariableDeclExpr v |
74+
t.getACatchClause() = cc and
75+
cc.getVariable() = v and
76+
v.getType().(RefType).getASubtype*() instanceof NumberFormatException
77+
)
78+
}
79+
80+
/** Holds if NFE is thrown */
81+
predicate throwsNFE(Expr e) {
82+
e.(SpecialClassInstanceExpr).throwsNFE() or e.(SpecialMethodAccess).throwsNFE()
83+
}

0 commit comments

Comments
 (0)