From 450ff26694e26853cd3ea5cd556b9f0b3033b990 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Fri, 6 Nov 2020 13:25:00 +0000 Subject: [PATCH] Convert the query to a library --- .../NumberFormatException.ql | 66 +-------------- .../code/java/NumberFormatException.qll | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+), 65 deletions(-) create mode 100644 java/ql/src/semmle/code/java/NumberFormatException.qll diff --git a/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql b/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql index 1dada0980d0..5bda22051ea 100644 --- a/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql +++ b/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql @@ -11,71 +11,7 @@ */ import java - -private class SpecialMethodAccess extends MethodAccess { - predicate isValueOfMethod(string klass) { - this.getMethod().getName() = "valueOf" and - this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) and - this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String") - } - - predicate isParseMethod(string klass, string name) { - this.getMethod().getName() = name and - this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) - } - - predicate throwsNFE() { - this.isParseMethod("Byte", "parseByte") or - this.isParseMethod("Short", "parseShort") or - this.isParseMethod("Integer", "parseInt") or - this.isParseMethod("Long", "parseLong") or - this.isParseMethod("Float", "parseFloat") or - this.isParseMethod("Double", "parseDouble") or - this.isParseMethod("Byte", "decode") or - this.isParseMethod("Short", "decode") or - this.isParseMethod("Integer", "decode") or - this.isParseMethod("Long", "decode") or - this.isValueOfMethod("Byte") or - this.isValueOfMethod("Short") or - this.isValueOfMethod("Integer") or - this.isValueOfMethod("Long") or - this.isValueOfMethod("Float") or - this.isValueOfMethod("Double") - } -} - -private class SpecialClassInstanceExpr extends ClassInstanceExpr { - predicate isStringConstructor(string klass) { - this.getType().(RefType).hasQualifiedName("java.lang", klass) and - this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String") and - this.getNumArgument() = 1 - } - - predicate throwsNFE() { - this.isStringConstructor("Byte") or - this.isStringConstructor("Short") or - this.isStringConstructor("Integer") or - this.isStringConstructor("Long") or - this.isStringConstructor("Float") or - this.isStringConstructor("Double") - } -} - -class NumberFormatException extends RefType { - NumberFormatException() { this.hasQualifiedName("java.lang", "NumberFormatException") } -} - -private predicate catchesNFE(TryStmt t) { - exists(CatchClause cc, LocalVariableDeclExpr v | - t.getACatchClause() = cc and - cc.getVariable() = v and - v.getType().(RefType).getASubtype*() instanceof NumberFormatException - ) -} - -private predicate throwsNFE(Expr e) { - e.(SpecialClassInstanceExpr).throwsNFE() or e.(SpecialMethodAccess).throwsNFE() -} +import semmle.code.java.NumberFormatException from Expr e where diff --git a/java/ql/src/semmle/code/java/NumberFormatException.qll b/java/ql/src/semmle/code/java/NumberFormatException.qll new file mode 100644 index 00000000000..1d3fbce63dd --- /dev/null +++ b/java/ql/src/semmle/code/java/NumberFormatException.qll @@ -0,0 +1,83 @@ +/** + * @name Missing catch of NumberFormatException + * @description Calling a string to number conversion method without handling + * 'NumberFormatException' may cause unexpected runtime exceptions. + * @kind problem + * @problem.severity recommendation + * @precision high + * @id java/uncaught-number-format-exception + * @tags reliability + * external/cwe/cwe-248 + */ + +import java + +/** Calls a string to number conversion */ +private class SpecialMethodAccess extends MethodAccess { + predicate isValueOfMethod(string klass) { + this.getMethod().getName() = "valueOf" and + this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) and + this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String") + } + + predicate isParseMethod(string klass, string name) { + this.getMethod().getName() = name and + this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) + } + + predicate throwsNFE() { + this.isParseMethod("Byte", "parseByte") or + this.isParseMethod("Short", "parseShort") or + this.isParseMethod("Integer", "parseInt") or + this.isParseMethod("Long", "parseLong") or + this.isParseMethod("Float", "parseFloat") or + this.isParseMethod("Double", "parseDouble") or + this.isParseMethod("Byte", "decode") or + this.isParseMethod("Short", "decode") or + this.isParseMethod("Integer", "decode") or + this.isParseMethod("Long", "decode") or + this.isValueOfMethod("Byte") or + this.isValueOfMethod("Short") or + this.isValueOfMethod("Integer") or + this.isValueOfMethod("Long") or + this.isValueOfMethod("Float") or + this.isValueOfMethod("Double") + } +} + +/** Constructs a number from its string representation */ +private class SpecialClassInstanceExpr extends ClassInstanceExpr { + predicate isStringConstructor(string klass) { + this.getType().(RefType).hasQualifiedName("java.lang", klass) and + this.getAnArgument().getType().(RefType).hasQualifiedName("java.lang", "String") and + this.getNumArgument() = 1 + } + + predicate throwsNFE() { + this.isStringConstructor("Byte") or + this.isStringConstructor("Short") or + this.isStringConstructor("Integer") or + this.isStringConstructor("Long") or + this.isStringConstructor("Float") or + this.isStringConstructor("Double") + } +} + +/** The class `java.lang.NumberFormatException` */ +class NumberFormatException extends RefType { + NumberFormatException() { this.hasQualifiedName("java.lang", "NumberFormatException") } +} + +/** Holds if NFE is caught */ +predicate catchesNFE(TryStmt t) { + exists(CatchClause cc, LocalVariableDeclExpr v | + t.getACatchClause() = cc and + cc.getVariable() = v and + v.getType().(RefType).getASubtype*() instanceof NumberFormatException + ) +} + +/** Holds if NFE is thrown */ +predicate throwsNFE(Expr e) { + e.(SpecialClassInstanceExpr).throwsNFE() or e.(SpecialMethodAccess).throwsNFE() +}