Java: Autoformat most queries.

This commit is contained in:
Anders Schack-Mulligen
2018-10-10 17:49:12 +02:00
parent 85cca69721
commit dd5a8f0c14
443 changed files with 2548 additions and 2043 deletions

View File

@@ -8,16 +8,13 @@
* @id java/missing-override-annotation
* @tags maintainability
*/
import java
class OverridingMethod extends Method {
OverridingMethod() {
exists(Method m | this.overrides(m))
}
OverridingMethod() { exists(Method m | this.overrides(m)) }
predicate isOverrideAnnotated() {
this.getAnAnnotation() instanceof OverrideAnnotation
}
predicate isOverrideAnnotated() { this.getAnAnnotation() instanceof OverrideAnnotation }
}
from OverridingMethod m, Method overridden
@@ -26,5 +23,5 @@ where
m.overrides(overridden) and
not m.isOverrideAnnotated() and
not exists(FunctionalExpr mref | mref.asMethod() = m)
select m, "This method overrides $@; it is advisable to add an Override annotation.",
overridden, overridden.getDeclaringType() + "." + overridden.getName()
select m, "This method overrides $@; it is advisable to add an Override annotation.", overridden,
overridden.getDeclaringType() + "." + overridden.getName()

View File

@@ -9,6 +9,7 @@
* @id java/non-final-immutable-field
* @tags reliability
*/
import java
class Initialization extends Callable {
@@ -41,7 +42,8 @@ class ImmutableField extends Field {
forall(FieldAccess fw, AnyAssignment ae |
fw.getField().getSourceDeclaration() = this and
fw = ae.getDest()
| ae.getEnclosingCallable().getDeclaringType() = this.getDeclaringType() and
|
ae.getEnclosingCallable().getDeclaringType() = this.getDeclaringType() and
ae.getEnclosingCallable() instanceof Initialization
)
}
@@ -49,4 +51,5 @@ class ImmutableField extends Field {
from ImmutableField f
where not f.isFinal()
select f, "This immutable field is not declared final but is only assigned to during initialization."
select f,
"This immutable field is not declared final but is only assigned to during initialization."

View File

@@ -8,6 +8,7 @@
* @id java/non-private-field
* @tags maintainability
*/
import java
import semmle.code.java.JDKAnnotations

View File

@@ -10,10 +10,10 @@
* non-attributable
* external/cwe/cwe-477
*/
import java
private
predicate isDeprecatedCallable(Callable c) {
private predicate isDeprecatedCallable(Callable c) {
c.getAnAnnotation() instanceof DeprecatedAnnotation or
exists(c.getDoc().getJavadoc().getATag("@deprecated"))
}
@@ -24,5 +24,5 @@ where
isDeprecatedCallable(c) and
// Exclude deprecated calls from within deprecated code.
not isDeprecatedCallable(ca.getCaller())
select ca, "Invoking $@ should be avoided because it has been deprecated.",
c, c.getDeclaringType() + "." + c.getName()
select ca, "Invoking $@ should be avoided because it has been deprecated.", c,
c.getDeclaringType() + "." + c.getName()

View File

@@ -19,9 +19,10 @@ RefType getTaggedType(ThrowsTag tag) {
predicate canThrow(Callable callable, RefType exception) {
exists(string uncheckedException |
uncheckedException = "RuntimeException" or uncheckedException = "Error"
|
|
exception.getASupertype*().hasQualifiedName("java.lang", uncheckedException)
) or
)
or
callable.getAnException().getType().getASubtype*() = exception
}
@@ -31,4 +32,5 @@ where
docMethod.getDoc().getJavadoc().getAChild*() = throwsTag and
not canThrow(docMethod, thrownType)
select throwsTag,
"Javadoc for " + docMethod + " claims to throw " + thrownType.getName() + " but this is impossible."
"Javadoc for " + docMethod + " claims to throw " + thrownType.getName() +
" but this is impossible."

View File

@@ -8,9 +8,11 @@
* @id java/undocumented-function
* @tags maintainability
*/
import java
import JavadocCommon
from DocuCallable c
where not c.hasAcceptableDocText()
select c, "This " + c.toMethodOrConstructorString() + " does not have a non-trivial Javadoc comment."
select c,
"This " + c.toMethodOrConstructorString() + " does not have a non-trivial Javadoc comment."

View File

@@ -8,6 +8,7 @@
* @id java/undocumented-parameter
* @tags maintainability
*/
import java
import JavadocCommon

View File

@@ -8,6 +8,7 @@
* @id java/undocumented-return-value
* @tags maintainability
*/
import java
import JavadocCommon

View File

@@ -8,6 +8,7 @@
* @id java/undocumented-exception
* @tags maintainability
*/
import java
import JavadocCommon
@@ -18,5 +19,6 @@ where
e.getType() = t and
not c.hasAcceptableThrowsTag(e)
)
select c, "This " + c.toMethodOrConstructorString() + " throws $@ but does not have a corresponding Javadoc tag.",
t, t.getName()
select c,
"This " + c.toMethodOrConstructorString() +
" throws $@ but does not have a corresponding Javadoc tag.", t, t.getName()

View File

@@ -8,6 +8,7 @@
* @id java/undocumented-type
* @tags maintainability
*/
import java
import JavadocCommon

View File

@@ -13,20 +13,17 @@ import java
from Callable callable, ParamTag paramTag, string what, string msg
where
callable.(Documentable).getJavadoc().getAChild() = paramTag and
( if callable instanceof Constructor
then what = "constructor"
else what = "method"
) and
if exists(paramTag.getParamName()) then (
(if callable instanceof Constructor then what = "constructor" else what = "method") and
if exists(paramTag.getParamName())
then (
// The tag's value is neither matched by a callable parameter name ...
not callable.getAParameter().getName() = paramTag.getParamName() and
// ... nor by a type parameter name.
not exists(TypeVariable tv | tv.getGenericCallable() = callable |
"<" + tv.getName() + ">" = paramTag.getParamName()
) and
msg = "@param tag \"" + paramTag.getParamName()
+ "\" does not match any actual parameter of " + what + " \""
+ callable.getName() + "()\"."
msg = "@param tag \"" + paramTag.getParamName() + "\" does not match any actual parameter of " +
what + " \"" + callable.getName() + "()\"."
) else
// The tag has no value at all.
msg = "This @param tag does not have a value."

View File

@@ -8,6 +8,7 @@
* @id java/use-of-clone-method
* @tags reliability
*/
import java
class ObjectCloneMethod extends Method {

View File

@@ -8,6 +8,7 @@
* @id java/override-of-clone-method
* @tags reliability
*/
import java
class ObjectCloneMethod extends Method {

View File

@@ -8,6 +8,7 @@
* @id java/use-of-cloneable-interface
* @tags reliability
*/
import java
from RefType t

View File

@@ -7,6 +7,7 @@
* @id java/override-of-finalize-method
* @tags reliability
*/
import java
class ObjectFinalizeMethod extends Method {

View File

@@ -7,6 +7,7 @@
* @id java/misnamed-constant
* @tags maintainability
*/
import java
import NamingConventionsCommon

View File

@@ -7,6 +7,7 @@
* @id java/misnamed-function
* @tags maintainability
*/
import java
from Method m

View File

@@ -7,6 +7,7 @@
* @id java/misnamed-package
* @tags maintainability
*/
import java
from RefType t, Package p
@@ -14,4 +15,6 @@ where
p = t.getPackage() and
t.fromSource() and
not p.getName().toLowerCase() = p.getName()
select t, "This type belongs to the package " + p.getName() + ", which should not include uppercase letters."
select t,
"This type belongs to the package " + p.getName() +
", which should not include uppercase letters."

View File

@@ -7,6 +7,7 @@
* @id java/misnamed-type
* @tags maintainability
*/
import java
from RefType t

View File

@@ -7,6 +7,7 @@
* @id java/misnamed-variable
* @tags maintainability
*/
import java
import NamingConventionsCommon

View File

@@ -7,12 +7,14 @@
* @id java/multiple-statements-on-same-line
* @tags maintainability
*/
import java
predicate lineDefinesEnum(File f, int line) {
exists(Location l |
exists(EnumType e | e.getLocation() = l) or
exists(EnumConstant e | e.getLocation() = l) |
exists(EnumConstant e | e.getLocation() = l)
|
f = l.getFile() and line = l.getStartLine()
)
}

View File

@@ -8,6 +8,7 @@
* @id java/raw-constructor-invocation
* @tags maintainability
*/
import java
from ClassInstanceExpr cie

View File

@@ -8,6 +8,7 @@
* @id java/raw-return-type
* @tags maintainability
*/
import java
from Method m

View File

@@ -8,6 +8,7 @@
* @id java/raw-variable
* @tags maintainability
*/
import java
from Variable v

View File

@@ -17,73 +17,61 @@ class SuppressionComment extends Javadoc {
isEolComment(this) and
exists(string text | text = getChild(0).getText() |
// match `lgtm[...]` anywhere in the comment
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)
or
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _) or
// match `lgtm` at the start of the comment and after semicolon
annotation = text.regexpFind("(?i)(?<=^|;)\\s*lgtm(?!\\B|\\s*\\[)", _, _).trim()
)
}
/**
* Gets the text of this suppression comment.
*/
string getText() {
result = getChild(0).getText()
}
* Gets the text of this suppression comment.
*/
string getText() { result = getChild(0).getText() }
/** Gets the suppression annotation in this comment. */
string getAnnotation() {
result = annotation
}
string getAnnotation() { result = annotation }
/**
* Holds if this comment applies to the range from column `startcolumn` of line `startline`
* to column `endcolumn` of line `endline` in file `filepath`.
*/
* Holds if this comment applies to the range from column `startcolumn` of line `startline`
* to column `endcolumn` of line `endline` in file `filepath`.
*/
predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and
startcolumn = 1
}
/** Gets the scope of this suppression. */
SuppressionScope getScope() {
this = result.getSuppressionComment()
}
SuppressionScope getScope() { this = result.getSuppressionComment() }
}
/**
* The scope of an alert suppression comment.
*/
class SuppressionScope extends @javadoc {
SuppressionScope() {
this instanceof SuppressionComment
}
SuppressionScope() { this instanceof SuppressionComment }
/** Gets a suppression comment with this scope. */
SuppressionComment getSuppressionComment() {
result = this
}
SuppressionComment getSuppressionComment() { result = this }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [LGTM locations](https://lgtm.com/help/ql/locations).
*/
predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [LGTM locations](https://lgtm.com/help/ql/locations).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets a textual representation of this element. */
string toString() {
result = "suppression range"
}
string toString() { result = "suppression range" }
}
from SuppressionComment c
select
c, // suppression comment
c.getText(), // text of suppression comment (excluding delimiters)
select c, // suppression comment
c.getText(), // text of suppression comment (excluding delimiters)
c.getAnnotation(), // text of suppression annotation
c.getScope() // scope of suppression
c.getScope() // scope of suppression

View File

@@ -32,5 +32,4 @@ where
t2.getAMethod().getName().toLowerCase().matches("%visit%") or
t1.getPackage() = t2.getPackage()
)
select t1, "This type and type $@ are mutually dependent.",
t2, t2.getName()
select t1, "This type and type $@ are mutually dependent.", t2, t2.getName()

View File

@@ -10,6 +10,7 @@
* @tags maintainability
* modularity
*/
import java
Member getAUsedMember(Method m) {
@@ -21,9 +22,7 @@ int dependencyCount(Method source, RefType target) {
result = strictcount(Member m | m = getAUsedMember(source) and m = target.getAMember())
}
predicate methodDependsOn(Method m, RefType target) {
exists(dependencyCount(m, target))
}
predicate methodDependsOn(Method m, RefType target) { exists(dependencyCount(m, target)) }
predicate dependsOn(RefType source, RefType target) {
methodDependsOn(source.getACallable(), target)
@@ -36,7 +35,7 @@ int selfDependencyCount(Method source) {
predicate dependsHighlyOn(Method source, RefType target, int selfCount, int depCount) {
depCount = dependencyCount(source, target) and
selfCount = selfDependencyCount(source) and
depCount > 2*selfCount and
depCount > 2 * selfCount and
depCount > 4
}
@@ -69,6 +68,7 @@ where
// Don't include types that are used from many different places - we only highlight
// relatively local fixes that could reasonably be implemented.
count(Method yetAnotherMethod | query(yetAnotherMethod, other, _, _)) < 10
select m, "Method " + m.getName() + " is too closely tied to $@: " + depCount +
" dependencies to it, but only " + selfCount + " dependencies to its own type.",
other, other.getName()
select m,
"Method " + m.getName() + " is too closely tied to $@: " + depCount +
" dependencies to it, but only " + selfCount + " dependencies to its own type.", other,
other.getName()

View File

@@ -9,6 +9,7 @@
* @tags maintainability
* modularity
*/
import java
from RefType t, int aff, int eff
@@ -16,6 +17,8 @@ where
t.fromSource() and
aff = t.getMetrics().getAfferentCoupling() and
eff = t.getMetrics().getEfferentSourceCoupling() and
aff > 15 and eff > 15
aff > 15 and
eff > 15
select t as Class,
"Hub class: this class depends on " + eff.toString() + " classes and is used by " + aff.toString() + " classes."
"Hub class: this class depends on " + eff.toString() + " classes and is used by " + aff.toString()
+ " classes."

View File

@@ -9,6 +9,7 @@
* @tags maintainability
* modularity
*/
import java
predicate enclosingRefType(Variable v, RefType type) {
@@ -60,5 +61,6 @@ where
cb > 20 and
ca >= cb and
not exists(CompilationUnit cu | cu = a.getCompilationUnit() and cu = b.getCompilationUnit())
select a, "Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() +
" dependencies one way and " + cb.toString() + " the other).", b, b.getName()
select a,
"Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() +
" dependencies one way and " + cb.toString() + " the other).", b, b.getName()

View File

@@ -8,6 +8,7 @@
* @id java/jdk-internal-api-access
* @tags maintainability
*/
import java
import JdkInternals
import JdkInternalsReplacement
@@ -24,72 +25,83 @@ predicate importedPackage(Import i, Package p) {
}
predicate typeReplacement(RefType t, string repl) {
exists(string old | jdkInternalReplacement(old, repl) |
t.getQualifiedName() = old
)
exists(string old | jdkInternalReplacement(old, repl) | t.getQualifiedName() = old)
}
predicate packageReplacementForType(RefType t, string repl) {
exists(string old, string pkgName |
jdkInternalReplacement(old, repl) and t.getPackage().getName() = pkgName
|
|
pkgName = old or
pkgName.prefix(old.length()+1) = old + "."
pkgName.prefix(old.length() + 1) = old + "."
)
}
predicate packageReplacement(Package p, string repl) {
exists(string old | jdkInternalReplacement(old, repl) |
p.getName() = old or
p.getName().prefix(old.length()+1) = old + "."
p.getName().prefix(old.length() + 1) = old + "."
)
}
predicate replacement(RefType t, string repl) {
typeReplacement(t, repl) or
typeReplacement(t, repl)
or
not typeReplacement(t, _) and packageReplacementForType(t, repl)
}
abstract class JdkInternalAccess extends Element {
abstract string getAccessedApi();
abstract string getReplacement();
}
class JdkInternalTypeAccess extends JdkInternalAccess, TypeAccess {
JdkInternalTypeAccess() {
jdkInternalApi(this.getType().(RefType).getPackage().getName())
}
override string getAccessedApi() {
result = getType().(RefType).getQualifiedName()
}
JdkInternalTypeAccess() { jdkInternalApi(this.getType().(RefType).getPackage().getName()) }
override string getAccessedApi() { result = getType().(RefType).getQualifiedName() }
override string getReplacement() {
exists(RefType t | this.getType() = t |
(replacement(t, result) or not replacement(t, _) and result = "unknown")
(
replacement(t, result)
or
not replacement(t, _) and result = "unknown"
)
)
}
}
class JdkInternalImport extends JdkInternalAccess, Import {
JdkInternalImport() {
exists(RefType t | importedType(this, t) |
jdkInternalApi(t.getPackage().getName())
) or
exists(Package p | importedPackage(this, p) |
jdkInternalApi(p.getName())
)
exists(RefType t | importedType(this, t) | jdkInternalApi(t.getPackage().getName()))
or
exists(Package p | importedPackage(this, p) | jdkInternalApi(p.getName()))
}
override string getAccessedApi() {
exists(RefType t | result = t.getQualifiedName() | importedType(this, t)) or
exists(RefType t | result = t.getQualifiedName() | importedType(this, t))
or
exists(Package p | result = p.getName() | importedPackage(this, p))
}
override string getReplacement() {
exists(RefType t |
importedType(this, t) and
(replacement(t, result) or not replacement(t, _) and result = "unknown")
) or
(
replacement(t, result)
or
not replacement(t, _) and result = "unknown"
)
)
or
exists(Package p |
importedPackage(this, p) and
(packageReplacement(p, result) or not packageReplacement(p, _) and result = "unknown")
(
packageReplacement(p, result)
or
not packageReplacement(p, _) and result = "unknown"
)
)
}
}
@@ -97,8 +109,8 @@ class JdkInternalImport extends JdkInternalAccess, Import {
predicate jdkPackage(Package p) {
exists(string pkgName |
p.getName() = pkgName or
p.getName().prefix(pkgName.length()+1) = pkgName + "."
|
p.getName().prefix(pkgName.length() + 1) = pkgName + "."
|
pkgName = "com.sun" or
pkgName = "sun" or
pkgName = "java" or
@@ -115,7 +127,7 @@ predicate jdkPackage(Package p) {
from JdkInternalAccess ta, string repl, string msg
where
repl = ta.getReplacement() and
(if (repl="unknown") then msg = "" else msg = " (" + repl + ")") and
(if (repl = "unknown") then msg = "" else msg = " (" + repl + ")") and
not jdkInternalApi(ta.getCompilationUnit().getPackage().getName()) and
not jdkPackage(ta.getCompilationUnit().getPackage())
select ta, "Access to unsupported JDK-internal API '" + ta.getAccessedApi() + "'." + msg

View File

@@ -8,6 +8,7 @@
* @id java/underscore-identifier
* @tags maintainability
*/
import java
class IdentifierElement extends Element {

View File

@@ -10,6 +10,7 @@
* testability
* complexity
*/
import java
class ComplexStmt extends Stmt {

View File

@@ -8,6 +8,7 @@
* @tags testability
* readability
*/
import java
predicate nontrivialLogicalOperator(BinaryExpr e) {

View File

@@ -16,8 +16,13 @@ import semmle.code.java.deadcode.DeadCode
from DeadField f, Element origin, string reason
where
not f.isInDeadScope() and
if exists(FieldRead read | read = f.getAnAccess()) then (
if exists(DeadRoot root | root = getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable())) then (
if exists(FieldRead read | read = f.getAnAccess())
then (
if
exists(DeadRoot root |
root = getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable())
)
then (
origin = getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable()) and
reason = " is only read from dead code originating at $@."
) else (

View File

@@ -9,25 +9,30 @@
* useless-code
* external/cwe/cwe-561
*/
import java
import semmle.code.java.deadcode.DeadCode
from DeadMethod c, Callable origin, string reason
where
not c.isInDeadScope() and
if exists(DeadRoot deadRoot | deadRoot = getADeadRoot(c) | deadRoot.getSourceDeclaration() != c) then (
if exists(DeadRoot deadRoot | deadRoot = getADeadRoot(c) | deadRoot.getSourceDeclaration() != c)
then (
// We've found a dead root that is not this callable (or an instantiation thereof).
origin = getADeadRoot(c).getSourceDeclaration() and
reason = " is only used from dead code originating at $@."
) else (
origin = c and
if exists(Callable cause | cause = possibleLivenessCause(c) and not cause instanceof DeadRoot |
cause.getSourceDeclaration() = c implies possibleLivenessCause(cause).getSourceDeclaration() != c)
if
exists(Callable cause | cause = possibleLivenessCause(c) and not cause instanceof DeadRoot |
cause.getSourceDeclaration() = c
implies
possibleLivenessCause(cause).getSourceDeclaration() != c
)
then
// There are no dead roots that are not this callable (or an instantiation thereof), and at least one
// liveness cause (ignoring trivial cycles between a parameterized callable and its source declaration).
reason = " is only used from, or in, a dead-code cycle."
else
reason = " is entirely unused."
else reason = " is entirely unused."
)
select c, "The method " + c.getName() + reason, origin, origin.getName()

View File

@@ -9,6 +9,7 @@
* useless-code
* external/cwe/cwe-561
*/
import semmle.code.java.deadcode.DeadCode
from RootdefCallable c

View File

@@ -13,25 +13,26 @@
* external/cwe/cwe-578
* external/cwe/cwe-382
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to create a class loader; obtain the current class loader;
set the context class loader; set security manager; create a new security manager; stop the
JVM; or change the input, output, and error streams.
These functions are reserved for the EJB container. Allowing the enterprise bean to use these functions
could compromise security and decrease the container's ability to properly manage the runtime envi-
ronment.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to create a class loader; obtain the current class loader;
* set the context class loader; set security manager; create a new security manager; stop the
* JVM; or change the input, output, and error streams.
*
* These functions are reserved for the EJB container. Allowing the enterprise bean to use these functions
* could compromise security and decrease the container's ability to properly manage the runtime envi-
* ronment.
*/
from Callable origin, ForbiddenContainerInterferenceCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not interfere with its container's operation by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not interfere with its container's operation by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -10,27 +10,28 @@
* @tags reliability
* external/cwe/cwe-576
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- An enterprise bean must not use the java.io package to attempt to access files and directo-
ries in the file system.
The file system APIs are not well-suited for business components to access data. Business components
should use a resource manager API, such as JDBC, to store data.
- The enterprise bean must not attempt to directly read or write a file descriptor.
Allowing the enterprise bean to read and write file descriptors directly could compromise security.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - An enterprise bean must not use the java.io package to attempt to access files and directo-
* ries in the file system.
*
* The file system APIs are not well-suited for business components to access data. Business components
* should use a resource manager API, such as JDBC, to store data.
*
* - The enterprise bean must not attempt to directly read or write a file descriptor.
*
* Allowing the enterprise bean to read and write file descriptors directly could compromise security.
*/
from Callable origin, ForbiddenFileCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not access the file system by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not access the file system by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -10,23 +10,24 @@
* @tags reliability
* external/cwe/cwe-575
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- An enterprise bean must not use the AWT functionality to attempt to output information to a
display, or to input information from a keyboard.
Most servers do not allow direct interaction between an application program and a keyboard/display
attached to the server system.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - An enterprise bean must not use the AWT functionality to attempt to output information to a
* display, or to input information from a keyboard.
*
* Most servers do not allow direct interaction between an application program and a keyboard/display
* attached to the server system.
*/
from Callable origin, ForbiddenGraphicsCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not use AWT or other graphics functionality by $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not use AWT or other graphics functionality by $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -9,22 +9,23 @@
* @tags reliability
* external/cwe/cwe-573
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to load a native library.
This function is reserved for the EJB container. Allowing the enterprise bean to load native code would
create a security hole.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to load a native library.
*
* This function is reserved for the EJB container. Allowing the enterprise bean to load native code would
* create a security hole.
*/
from Callable origin, ForbiddenNativeCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not use native code by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not use native code by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -8,25 +8,26 @@
* @id java/ejb/reflection
* @tags external/cwe/cwe-573
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to query a class to obtain information about the declared
members that are not otherwise accessible to the enterprise bean because of the security rules
of the Java language. The enterprise bean must not attempt to use the Reflection API to access
information that the security rules of the Java programming language make unavailable.
Allowing the enterprise bean to access information about other classes and to access the classes in a
manner that is normally disallowed by the Java programming language could compromise security.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to query a class to obtain information about the declared
* members that are not otherwise accessible to the enterprise bean because of the security rules
* of the Java language. The enterprise bean must not attempt to use the Reflection API to access
* information that the security rules of the Java programming language make unavailable.
*
* Allowing the enterprise bean to access information about other classes and to access the classes in a
* manner that is normally disallowed by the Java programming language could compromise security.
*/
from Callable origin, ForbiddenReflectionCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not use reflection by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not use reflection by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -9,28 +9,29 @@
* @id java/ejb/security-configuration-access
* @tags external/cwe/cwe-573
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to obtain the security policy information for a particular
code source.
Allowing the enterprise bean to access the security policy information would create a security hole.
- The enterprise bean must not attempt to access or modify the security configuration objects
(Policy, Security, Provider, Signer, and Identity).
These functions are reserved for the EJB container. Allowing the enterprise bean to use these functions
could compromise security.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to obtain the security policy information for a particular
* code source.
*
* Allowing the enterprise bean to access the security policy information would create a security hole.
*
* - The enterprise bean must not attempt to access or modify the security configuration objects
* (Policy, Security, Provider, Signer, and Identity).
*
* These functions are reserved for the EJB container. Allowing the enterprise bean to use these functions
* could compromise security.
*/
from Callable origin, ForbiddenSecurityConfigurationCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not access a security configuration by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not access a security configuration by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -8,22 +8,23 @@
* @id java/ejb/substitution-in-serialization
* @tags external/cwe/cwe-573
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to use the subclass and object substitution features of the
Java Serialization Protocol.
Allowing the enterprise bean to use these functions could compromise security.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to use the subclass and object substitution features of the
* Java Serialization Protocol.
*
* Allowing the enterprise bean to use these functions could compromise security.
*/
from Callable origin, ForbiddenSerializationCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not use a substitution feature of serialization by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName() + " $@"
select origin, "EJB should not use a substitution feature of serialization by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName() + " $@"

View File

@@ -10,24 +10,25 @@
* @tags reliability
* external/cwe/cwe-577
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to set the socket factory used by ServerSocket, Socket, or
the stream handler factory used by URL.
These networking functions are reserved for the EJB container. Allowing the enterprise bean to use
these functions could compromise security and decrease the container's ability to properly manage the
runtime environment.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to set the socket factory used by ServerSocket, Socket, or
* the stream handler factory used by URL.
*
* These networking functions are reserved for the EJB container. Allowing the enterprise bean to use
* these functions could compromise security and decrease the container's ability to properly manage the
* runtime environment.
*/
from Callable origin, ForbiddenSetFactoryCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not set a factory by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not set a factory by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -10,24 +10,25 @@
* @tags reliability
* external/cwe/cwe-577
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- An enterprise bean must not attempt to listen on a socket, accept connections on a socket, or
use a socket for multicast.
The EJB architecture allows an enterprise bean instance to be a network socket client, but it does not
allow it to be a network server. Allowing the instance to become a network server would conflict with
the basic function of the enterprise bean -- to serve the EJB clients.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - An enterprise bean must not attempt to listen on a socket, accept connections on a socket, or
* use a socket for multicast.
*
* The EJB architecture allows an enterprise bean instance to be a network socket client, but it does not
* allow it to be a network server. Allowing the instance to become a network server would conflict with
* the basic function of the enterprise bean -- to serve the EJB clients.
*/
from Callable origin, ForbiddenServerSocketCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not use a socket as a server by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not use a socket as a server by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -10,29 +10,29 @@
* @tags reliability
* external/cwe/cwe-573
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- An enterprise bean must not use read/write static fields. Using read-only static fields is
allowed. Therefore, it is recommended that all static fields in the enterprise bean class be
declared as final.
This rule is required to ensure consistent runtime semantics because while some EJB containers may
use a single JVM to execute all enterprise bean's instances, others may distribute the instances across
multiple JVMs.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - An enterprise bean must not use read/write static fields. Using read-only static fields is
* allowed. Therefore, it is recommended that all static fields in the enterprise bean class be
* declared as final.
*
* This rule is required to ensure consistent runtime semantics because while some EJB containers may
* use a single JVM to execute all enterprise bean's instances, others may distribute the instances across
* multiple JVMs.
*/
from Callable origin, ForbiddenStaticFieldCallable target, Call call, FieldAccess fa, Field f
where
ejbCalls(origin, target, call) and
fa = forbiddenStaticFieldUse(target) and
fa.getField() = f
select origin, "EJB should not access non-final static field $@ $@.",
f, f.getDeclaringType().getName() + "." + f.getName(),
fa, "here"
select origin, "EJB should not access non-final static field $@ $@.", f,
f.getDeclaringType().getName() + "." + f.getName(), fa, "here"

View File

@@ -9,23 +9,24 @@
* @tags reliability
* external/cwe/cwe-574
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- An enterprise bean must not use thread synchronization primitives to synchronize execution of
multiple instances.
This is for the same reason as above. Synchronization would not work if the EJB container distributed
enterprise bean's instances across multiple JVMs.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - An enterprise bean must not use thread synchronization primitives to synchronize execution of
* multiple instances.
*
* This is for the same reason as above. Synchronization would not work if the EJB container distributed
* enterprise bean's instances across multiple JVMs.
*/
from Callable origin, ForbiddenSynchronizationCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not use synchronization by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not use synchronization by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -11,24 +11,24 @@
* @tags portability
* external/cwe/cwe-573
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to pass this as an argument or method result. The
enterprise bean must pass the result of SessionContext.getBusinessObject,
SessionContext.getEJBObject, SessionContext.getEJBLocalObject,
EntityContext.getEJBObject, or EntityContext.getEJBLocalObject instead.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to pass this as an argument or method result. The
* enterprise bean must pass the result of SessionContext.getBusinessObject,
* SessionContext.getEJBObject, SessionContext.getEJBLocalObject,
* EntityContext.getEJBObject, or EntityContext.getEJBLocalObject instead.
*/
from Callable origin, ForbiddenThisCallable target, Call call, ThisAccess ta
where
ejbCalls(origin, target, call) and
ta = forbiddenThisUse(target)
select origin, "EJB should not use 'this' as a method argument or result $@.",
ta, "here"
select origin, "EJB should not use 'this' as a method argument or result $@.", ta, "here"

View File

@@ -10,24 +10,25 @@
* external/cwe/cwe-383
* external/cwe/cwe-573
*/
import java
import semmle.code.java.frameworks.javaee.ejb.EJB
import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
/*
JSR 220: Enterprise JavaBeansTM,Version 3.0
EJB Core Contracts and Requirements
Section 21.1.2 Programming Restrictions
- The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt
to start, stop, suspend, or resume a thread, or to change a thread's priority or name. The enter-
prise bean must not attempt to manage thread groups.
These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads
would decrease the container's ability to properly manage the runtime environment.
*/
* JSR 220: Enterprise JavaBeansTM,Version 3.0
* EJB Core Contracts and Requirements
* Section 21.1.2 Programming Restrictions
*
* - The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt
* to start, stop, suspend, or resume a thread, or to change a thread's priority or name. The enter-
* prise bean must not attempt to manage thread groups.
*
* These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads
* would decrease the container's ability to properly manage the runtime environment.
*/
from Callable origin, ForbiddenThreadingCallable target, Call call
where ejbCalls(origin, target, call)
select origin, "EJB should not attempt to manage threads by calling $@.",
call, target.getDeclaringType().getName() + "." + target.getName()
select origin, "EJB should not attempt to manage threads by calling $@.", call,
target.getDeclaringType().getName() + "." + target.getName()

View File

@@ -9,6 +9,7 @@
* @tags maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring
@@ -35,5 +36,4 @@ where
select bean1,
"Bean $@ has " + similarProps.toString() +
" properties similar to $@. Consider introducing a common parent bean for these two beans.",
bean1, bean1.getBeanIdentifier(),
bean2, bean2.getBeanIdentifier()
bean1, bean1.getBeanIdentifier(), bean2, bean2.getBeanIdentifier()

View File

@@ -8,6 +8,7 @@
* @tags maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring

View File

@@ -9,19 +9,16 @@
* @tags maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring
from
SpringBean bean,
SpringProperty prop,
SpringProperty overriddenProp,
SpringBean ancestorBean
from SpringBean bean, SpringProperty prop, SpringProperty overriddenProp, SpringBean ancestorBean
where
prop = bean.getADeclaredProperty() and
ancestorBean = bean.getBeanParent+() and
ancestorBean.getADeclaredProperty() = overriddenProp and
overriddenProp.getPropertyName() = prop.getPropertyName() and
prop.isSimilar(overriddenProp)
select prop, "Property overrides $@ in parent, but has the same contents.",
overriddenProp, overriddenProp.toString()
select prop, "Property overrides $@ in parent, but has the same contents.", overriddenProp,
overriddenProp.toString()

View File

@@ -8,6 +8,7 @@
* @tags maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring

View File

@@ -9,6 +9,7 @@
* @tags maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring

View File

@@ -9,8 +9,8 @@
* @tags maintainability
* frameworks/spring
*/
import java
import java
import semmle.code.java.frameworks.spring.Spring
from SpringImport i

View File

@@ -7,9 +7,13 @@
* @id java/spring/missing-bean-description
* @tags maintainability
*/
import java
import semmle.code.java.frameworks.spring.Spring
from SpringBean b
where not exists(SpringDescription d | d = b.getASpringChild() or d = b.getSpringBeanFile().getBeansElement().getAChild())
where
not exists(SpringDescription d |
d = b.getASpringChild() or d = b.getSpringBeanFile().getBeansElement().getAChild()
)
select b, "This bean does not have a description."

View File

@@ -10,14 +10,12 @@
* maintainability
* frameworks/spring
*/
import java
import java
import semmle.code.java.frameworks.spring.Spring
class ParentBean extends SpringBean {
ParentBean() {
exists(SpringBean b | b.getBeanParent() = this)
}
ParentBean() { exists(SpringBean b | b.getBeanParent() = this) }
RefType getDeclaredClass() {
result = this.getClass() and
@@ -28,5 +26,5 @@ class ParentBean extends SpringBean {
from ParentBean parent
where parent.getDeclaredClass().isAbstract()
select parent, "Parent bean $@ should not have an abstract class.",
parent, parent.getBeanIdentifier()
select parent, "Parent bean $@ should not have an abstract class.", parent,
parent.getBeanIdentifier()

View File

@@ -10,6 +10,7 @@
* maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring
@@ -17,4 +18,5 @@ from SpringBean b
where
not b.hasBeanId() and
b.hasBeanName()
select b, "Use \"id\" instead of \"name\" to take advantage of the IDREF constraint in the XML parser."
select b,
"Use \"id\" instead of \"name\" to take advantage of the IDREF constraint in the XML parser."

View File

@@ -10,6 +10,7 @@
* maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring

View File

@@ -9,6 +9,7 @@
* @tags maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring

View File

@@ -8,6 +8,7 @@
* @tags maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring
@@ -52,7 +53,9 @@ class SpringPropertyUseShortcut extends SpringProperty {
from SpringXMLElement springElement, string msg
where
exists(SpringConstructorArgUseShortcut cons | cons = springElement and msg = cons.getMessage()) or
exists(SpringEntryUseShortcut entry | entry = springElement and msg = entry.getMessage()) or
exists(SpringConstructorArgUseShortcut cons | cons = springElement and msg = cons.getMessage())
or
exists(SpringEntryUseShortcut entry | entry = springElement and msg = entry.getMessage())
or
exists(SpringPropertyUseShortcut prop | prop = springElement and msg = prop.getMessage())
select springElement, msg

View File

@@ -10,6 +10,7 @@
* maintainability
* frameworks/spring
*/
import java
import semmle.code.java.frameworks.spring.Spring
@@ -17,5 +18,5 @@ from SpringProperty p
where
not p.getEnclosingBean().isAbstract() and
not exists(p.getSetterMethod())
select p, "This property is missing a setter method on $@.",
p.getEnclosingBean().getClass() as c, c.getName()
select p, "This property is missing a setter method on $@.", p.getEnclosingBean().getClass() as c,
c.getName()

View File

@@ -22,6 +22,6 @@ where
dest = cse.getType()
) and
dest.getGenericType() = src
select e, "Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.",
dest, dest.getName(),
src, src.getName()
select e,
"Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.",
dest, dest.getName(), src, src.getName()

View File

@@ -14,18 +14,11 @@ import java
int instanceofCountForIfChain(IfStmt is) {
exists(int rest |
(
if is.getElse() instanceof IfStmt then
rest = instanceofCountForIfChain(is.getElse())
else
rest = 0
)
and
(
if is.getCondition() instanceof InstanceOfExpr then
result = 1 + rest
else
result = rest
)
if is.getElse() instanceof IfStmt
then rest = instanceofCountForIfChain(is.getElse())
else rest = 0
) and
(if is.getCondition() instanceof InstanceOfExpr then result = 1 + rest else result = rest)
)
}
@@ -36,4 +29,4 @@ where
not exists(IfStmt other | is = other.getElse())
select is,
"This if block performs a chain of " + n +
" type tests - consider alternatives, e.g. polymorphism or the visitor pattern."
" type tests - consider alternatives, e.g. polymorphism or the visitor pattern."

View File

@@ -25,5 +25,4 @@ where
src != dest and
not dest instanceof TypeVariable
select e, "Downcasting 'this' from $@ to $@ introduces a dependency cycle between the two types.",
src, src.getName(),
dest, dest.getName()
src, src.getName(), dest, dest.getName()

View File

@@ -19,6 +19,6 @@ where
t = ioe.getExpr().getType() and
ct = ioe.getTypeName().getType() and
ct.getASupertype*() = t
select ioe, "Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.",
ct, ct.getName(),
t, t.getName()
select ioe,
"Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.",
ct, ct.getName(), t, t.getName()

View File

@@ -13,7 +13,8 @@ import java
from EmptyStmt empty, string action
where
if exists(LoopStmt l | l.getBody() = empty) then (
if exists(LoopStmt l | l.getBody() = empty)
then (
action = "turned into '{}'"
) else (
action = "deleted"

View File

@@ -13,9 +13,9 @@
import java
Element elementNamedEnum() {
result.(CompilationUnit).getPackage().getName().regexpMatch("(.*\\.|)enum(\\..*|)")
or
result.(CompilationUnit).getPackage().getName().regexpMatch("(.*\\.|)enum(\\..*|)") or
result.getName() = "enum"
}
select elementNamedEnum(), "Code using 'enum' as an identifier will not compile with a recent version of Java."
select elementNamedEnum(),
"Code using 'enum' as an identifier will not compile with a recent version of Java."

View File

@@ -14,4 +14,5 @@ import java
from RefType type, AnnotationType annotation
where type.getASupertype() = annotation
select type, "Should this class be annotated by '" + annotation.getName() + "', not have it as a super-type?"
select type,
"Should this class be annotated by '" + annotation.getName() + "', not have it as a super-type?"

View File

@@ -10,14 +10,13 @@
* @tags correctness
* reliability
*/
import java
import IterableClass
/** An `Iterable` that is also its own `Iterator`. */
class IterableIterator extends Iterable {
IterableIterator() {
simpleIterator() instanceof ThisAccess
}
IterableIterator() { simpleIterator() instanceof ThisAccess }
}
/** An `IterableIterator` that never returns any elements. */
@@ -26,7 +25,14 @@ class EmptyIterableIterator extends IterableIterator {
exists(Method m |
m.getDeclaringType().getSourceDeclaration() = this and
m.getName() = "hasNext" and
m.getBody().(SingletonBlock).getStmt().(ReturnStmt).getResult().(BooleanLiteral).getBooleanValue() = false
m
.getBody()
.(SingletonBlock)
.getStmt()
.(ReturnStmt)
.getResult()
.(BooleanLiteral)
.getBooleanValue() = false
)
}
}

View File

@@ -14,9 +14,7 @@
import java
predicate complicatedBranch(Stmt branch) {
exists(ConditionalExpr ce |
ce.getParent*() = branch
) or
exists(ConditionalExpr ce | ce.getParent*() = branch) or
count(MethodAccess a | a.getParent*() = branch) > 1
}
@@ -31,9 +29,11 @@ predicate toCompare(Expr left, Expr right) {
exists(IfStmt is, AssignExpr at, AssignExpr ae |
at.getParent() = is.getThen() and
ae.getParent() = is.getElse()
|
left = at.getDest() and right = ae.getDest() or
left = at.getDest().(VarAccess).getQualifier() and right = ae.getDest().(VarAccess).getQualifier()
|
left = at.getDest() and right = ae.getDest()
or
left = at.getDest().(VarAccess).getQualifier() and
right = ae.getDest().(VarAccess).getQualifier()
)
}
@@ -45,7 +45,8 @@ predicate sameVariable(VarAccess left, VarAccess right) {
left.getQualifier() = q1 and
sameVariable(q1, q2) and
right.getQualifier() = q2
) or
)
or
left.isLocal() and right.isLocal()
)
}
@@ -71,4 +72,5 @@ where
complicatedBranch(is.getThen()) or
complicatedBranch(is.getElse())
)
select is, "Both branches of this 'if' statement " + what + " - consider using '?' to express intent better."
select is,
"Both branches of this 'if' statement " + what + " - consider using '?' to express intent better."

View File

@@ -20,5 +20,4 @@ where
not superMethod.isProtected() and
not superMethod.isPrivate()
select method, "This method does not override $@ because it is private to another package.",
superMethod,
superMethod.getDeclaringType().getName() + "." + superMethod.getName()
superMethod, superMethod.getDeclaringType().getName() + "." + superMethod.getName()

View File

@@ -18,4 +18,5 @@ from TypeVariable v, RefType bound
where
v.getATypeBound().getType() = bound and
bound.isFinal()
select v, "Type '" + bound + "' is final, so <" + v.getName() + " extends " + bound + "> is confusing."
select v,
"Type '" + bound + "' is final, so <" + v.getName() + " extends " + bound + "> is confusing."

View File

@@ -14,10 +14,8 @@
import java
RefType anOuterType(TypeVariable var) {
var.getGenericCallable().getDeclaringType() = result
or
var.getGenericType() = result
or
var.getGenericCallable().getDeclaringType() = result or
var.getGenericType() = result or
result = anOuterType(var).(NestedType).getEnclosingType()
}

View File

@@ -19,10 +19,12 @@ from Expr guard, Expr e, Expr reason, string msg
where
guard = basicNullGuard(e, _, true) and
e = clearlyNotNullExpr(reason) and
(if reason instanceof Guard then
msg = "This check is useless, $@ cannot be null here, since it is guarded by $@."
else if reason != e then
msg = "This check is useless, $@ cannot be null here, since $@ always is non-null."
else
msg = "This check is useless, since $@ always is non-null.")
(
if reason instanceof Guard
then msg = "This check is useless, $@ cannot be null here, since it is guarded by $@."
else
if reason != e
then msg = "This check is useless, $@ cannot be null here, since $@ always is non-null."
else msg = "This check is useless, since $@ always is non-null."
)
select guard, msg, e, e.toString(), reason, reason.toString()

View File

@@ -17,6 +17,6 @@ where
t = ioe.getExpr().getType() and
ct = ioe.getTypeName().getType() and
ct = t.getASupertype+()
select ioe, "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.",
t, t.getName(),
ct, ct.getName()
select ioe,
"There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", t,
t.getName(), ct, ct.getName()

View File

@@ -19,13 +19,13 @@ predicate usefulUpcast(CastExpr e) {
target = c.getCallee() and
// An upcast to the type of the corresponding parameter.
e.getType() = target.getParameterType(i)
|
|
// There is an overloaded method/constructor in the class that we might be trying to avoid.
exists(Callable other |
other.getName() = target.getName() and
other.getSourceDeclaration() != target.getSourceDeclaration()
|
c.(MethodAccess).getReceiverType().(RefType).inherits((Method)other) or
|
c.(MethodAccess).getReceiverType().(RefType).inherits(other.(Method)) or
other = target.(Constructor).getDeclaringType().getAConstructor()
)
)
@@ -36,7 +36,9 @@ predicate usefulUpcast(CastExpr e) {
)
or
// Upcasts that are performed on an operand of a ternary expression.
exists(ConditionalExpr ce | e = ce.getTrueExpr().getProperExpr() or e = ce.getFalseExpr().getProperExpr())
exists(ConditionalExpr ce |
e = ce.getTrueExpr().getProperExpr() or e = ce.getFalseExpr().getProperExpr()
)
or
// Upcasts to raw types.
e.getType() instanceof RawType
@@ -46,10 +48,13 @@ predicate usefulUpcast(CastExpr e) {
// Upcasts that are performed to affect field, private method, or static method resolution.
exists(FieldAccess fa | e = fa.getQualifier().getProperExpr() |
not e.getExpr().getType().(RefType).inherits(fa.getField())
) or
)
or
exists(MethodAccess ma, Method m |
e = ma.getQualifier().getProperExpr() and m = ma.getMethod() and (m.isStatic() or m.isPrivate())
|
e = ma.getQualifier().getProperExpr() and
m = ma.getMethod() and
(m.isStatic() or m.isPrivate())
|
not e.getExpr().getType().(RefType).inherits(m)
)
}
@@ -63,6 +68,5 @@ where
) and
dest = src.getASupertype+() and
not usefulUpcast(e)
select e, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.",
src, src.getName(),
dest, dest.getName()
select e, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", src,
src.getName(), dest, dest.getName()

View File

@@ -9,6 +9,7 @@
* @tags correctness
* reliability
*/
import java
import IterableClass
@@ -18,18 +19,25 @@ predicate iteratorWrapper(Iterable it, Field f, boolean wrap) {
// declares a final or effectively final field ...
f.getDeclaringType().getSourceDeclaration() = it and
(
f.isFinal() or
f.isFinal()
or
(
strictcount(f.getAnAssignedValue()) = 1 and
f.getAnAssignedValue().getEnclosingCallable() instanceof InitializerMethod
)
) and
// ... whose type is a sub-type of `java.util.Iterator` and ...
f.getType().(RefType).getASupertype*().getSourceDeclaration().hasQualifiedName("java.util", "Iterator") and
f
.getType()
.(RefType)
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.util", "Iterator") and
// ... whose value is returned by the `iterator()` method of this class ...
exists(Expr iterator | iterator = it.simpleIterator() |
// ... either directly ...
iterator = f.getAnAccess() and wrap = false or
iterator = f.getAnAccess() and wrap = false
or
// ... or wrapped in another Iterator.
exists(ClassInstanceExpr cie | cie = iterator and wrap = true |
cie.getAnArgument() = f.getAnAccess() or
@@ -41,9 +49,11 @@ predicate iteratorWrapper(Iterable it, Field f, boolean wrap) {
from Iterable i, Field f, boolean wrap, string appearto, string iteratorbasedon
where
iteratorWrapper(i, f, wrap) and
( wrap = true and appearto = "appear to " and iteratorbasedon = "an iterator based on " or
(
wrap = true and appearto = "appear to " and iteratorbasedon = "an iterator based on "
or
wrap = false and appearto = "" and iteratorbasedon = ""
)
select i, "This class implements Iterable, but does not " + appearto + "support multiple iterations," +
" since its iterator method always returns " + iteratorbasedon + "the same $@.",
f, "iterator"
select i,
"This class implements Iterable, but does not " + appearto + "support multiple iterations," +
" since its iterator method always returns " + iteratorbasedon + "the same $@.", f, "iterator"

View File

@@ -9,16 +9,17 @@
* @tags reliability
* maintainability
*/
import java
from MethodAccess ma, Method abs, Method nextIntOrLong, MethodAccess nma
where
ma.getMethod() = abs and
abs.hasName("abs") and
abs.getDeclaringType().hasQualifiedName("java.lang","Math") and
abs.getDeclaringType().hasQualifiedName("java.lang", "Math") and
ma.getAnArgument() = nma and
nma.getMethod() = nextIntOrLong and
(nextIntOrLong.hasName("nextInt") or nextIntOrLong.hasName("nextLong")) and
nextIntOrLong.getDeclaringType().hasQualifiedName("java.util","Random") and
nextIntOrLong.getDeclaringType().hasQualifiedName("java.util", "Random") and
nextIntOrLong.hasNoParameters()
select ma, "Incorrect computation of abs of signed integral random value."

View File

@@ -10,6 +10,7 @@
* correctness
* types
*/
import java
import semmle.code.java.Collections
@@ -28,8 +29,10 @@ where
not isDefinitelyPositive(lhs.getLeftOperand()) and
lhs.getRightOperand().getProperExpr().(IntegerLiteral).getIntValue() = 2 and
(
t instanceof EQExpr and rhs.getIntValue() = 1 and parity = "oddness" or
t instanceof NEExpr and rhs.getIntValue() = 1 and parity = "evenness" or
t instanceof EQExpr and rhs.getIntValue() = 1 and parity = "oddness"
or
t instanceof NEExpr and rhs.getIntValue() = 1 and parity = "evenness"
or
t instanceof GTExpr and rhs.getIntValue() = 0 and parity = "oddness"
)
select t, "Possibly invalid test for " + parity + ". This will fail for negative numbers."

View File

@@ -9,16 +9,12 @@
* @tags reliability
* correctness
*/
import java
class CharType extends PrimitiveType {
CharType() {
this.hasName("char")
}
}
class CharType extends PrimitiveType { CharType() { this.hasName("char") } }
private
Type getABranchType(ConditionalExpr ce) {
private Type getABranchType(ConditionalExpr ce) {
result = ce.getTrueExpr().getType() or
result = ce.getFalseExpr().getType()
}
@@ -30,6 +26,5 @@ where
t instanceof PrimitiveType and
not t instanceof CharType
)
select ce, "Mismatch between types of branches: $@ and $@.",
ce.getTrueExpr(), ce.getTrueExpr().getType().getName(),
ce.getFalseExpr(), ce.getFalseExpr().getType().getName()
select ce, "Mismatch between types of branches: $@ and $@.", ce.getTrueExpr(),
ce.getTrueExpr().getType().getName(), ce.getFalseExpr(), ce.getFalseExpr().getType().getName()

View File

@@ -8,19 +8,16 @@
* @tags maintainability
* useless-code
*/
import java
int integralTypeWidth (IntegralType t) {
if (t.hasName("long") or t.hasName("Long"))
then result = 64
else result = 32
int integralTypeWidth(IntegralType t) {
if (t.hasName("long") or t.hasName("Long")) then result = 64 else result = 32
}
int eval (Expr e) {
result = e.(CompileTimeConstantExpr).getIntValue()
}
int eval(Expr e) { result = e.(CompileTimeConstantExpr).getIntValue() }
predicate isConstantExp (Expr e) {
predicate isConstantExp(Expr e) {
// A literal is constant.
e instanceof Literal
or
@@ -58,9 +55,7 @@ predicate isConstantExp (Expr e) {
)
)
or
exists(AndBitwiseExpr a | a = e |
eval(a.getAnOperand().getProperExpr()) = 0
)
exists(AndBitwiseExpr a | a = e | eval(a.getAnOperand().getProperExpr()) = 0)
or
exists(AndLogicalExpr a | a = e |
a.getAnOperand().getProperExpr().(BooleanLiteral).getBooleanValue() = false

View File

@@ -14,6 +14,7 @@
* external/cwe/cwe-197
* external/cwe/cwe-681
*/
import semmle.code.java.arithmetic.Overflow
class DangerousAssignOpExpr extends AssignOp {
@@ -23,14 +24,12 @@ class DangerousAssignOpExpr extends AssignOp {
}
}
predicate problematicCasting(Type t, Expr e) {
e.getType().(NumType).widerThan((NumType)t)
}
predicate problematicCasting(Type t, Expr e) { e.getType().(NumType).widerThan(t.(NumType)) }
from DangerousAssignOpExpr a, Expr e
where
e = a.getSource() and
problematicCasting(a.getDest().getType(), e)
select a,
"Implicit cast of source type " + e.getType().getName() +
" to narrower destination type " + a.getDest().getType().getName() + "."
"Implicit cast of source type " + e.getType().getName() + " to narrower destination type " +
a.getDest().getType().getName() + "."

View File

@@ -9,6 +9,7 @@
* @tags maintainability
* correctness
*/
import java
from MulExpr e

View File

@@ -11,6 +11,7 @@
* @tags maintainability
* correctness
*/
import java
from IntegerLiteral lit, string val

View File

@@ -10,11 +10,12 @@
* maintainability
* external/cwe/cwe-335
*/
import java
from MethodAccess ma, Method random
where
random.getDeclaringType().hasQualifiedName("java.util","Random") and
random.getDeclaringType().hasQualifiedName("java.util", "Random") and
ma.getMethod() = random and
ma.getQualifier() instanceof ClassInstanceExpr
select ma, "Random object created and used only once."

View File

@@ -70,9 +70,15 @@ class AssocNestedExpr extends BinaryExpr {
AssocNestedExpr() {
exists(BinaryExpr parent, int idx | this.isNthChildOf(parent, idx) |
// `+`, `*`, `&&`, `||` and the bitwise operations are associative.
((this instanceof AddExpr or this instanceof MulExpr or
this instanceof BitwiseExpr or this instanceof LogicalExpr) and
parent.getKind() = this.getKind())
(
(
this instanceof AddExpr or
this instanceof MulExpr or
this instanceof BitwiseExpr or
this instanceof LogicalExpr
) and
parent.getKind() = this.getKind()
)
or
// Equality tests are associate over each other.
(this instanceof EqualityTest and parent instanceof EqualityTest)
@@ -96,7 +102,10 @@ class AssocNestedExpr extends BinaryExpr {
class HarmlessNestedExpr extends BinaryExpr {
HarmlessNestedExpr() {
exists(BinaryExpr parent | this = parent.getAChildExpr() |
(parent instanceof RelationExpr and (this instanceof ArithmeticExpr or this instanceof ShiftExpr))
(
parent instanceof RelationExpr and
(this instanceof ArithmeticExpr or this instanceof ShiftExpr)
)
or
(parent instanceof LogicalExpr and this instanceof RelationExpr)
)
@@ -134,7 +143,9 @@ predicate interestingNesting(BinaryExpr inner, BinaryExpr outer) {
from BinaryExpr inner, BinaryExpr outer, int wsouter, int wsinner
where
interestingNesting(inner, outer) and
wsinner = operatorWS(inner) and wsouter = operatorWS(outer) and
wsinner % 2 = 0 and wsouter % 2 = 0 and
wsinner = operatorWS(inner) and
wsouter = operatorWS(outer) and
wsinner % 2 = 0 and
wsouter % 2 = 0 and
wsinner > wsouter
select outer, "Whitespace around nested operators contradicts precedence."

View File

@@ -11,6 +11,7 @@
* maintainability
* external/cwe/cwe-580
*/
import java
from CloneMethod c, CloneMethod sc
@@ -19,5 +20,5 @@ where
c.fromSource() and
exists(sc.getBody()) and
not exists(CloneMethod ssc | sc.callsSuper(ssc))
select sc, "This clone method does not call super.clone(), but is "
+ "overridden and called $@.", c, "in a subclass"
select sc, "This clone method does not call super.clone(), but is " + "overridden and called $@.",
c, "in a subclass"

View File

@@ -9,6 +9,7 @@
* @tags reliability
* maintainability
*/
import java
from Class t, TypeCloneable cloneable

View File

@@ -23,7 +23,7 @@ predicate boundedArrayAccess(ArrayAccess aa, int k) {
aa.getIndexExpr() = index and
aa.getArray() = arr.getAUse() and
bounded(index, b, delta, true, _)
|
|
exists(FieldAccess len |
len.getField() instanceof ArrayLengthField and
len.getQualifier() = arr.getAUse() and
@@ -33,13 +33,14 @@ predicate boundedArrayAccess(ArrayAccess aa, int k) {
or
exists(ArrayCreationExpr arraycreation |
arraycreation = arr.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource()
|
|
k = delta and
arraycreation.getDimension(0) = b.getExpr()
or
exists(int arrlen |
arraycreation.getFirstDimensionSize() = arrlen and
b instanceof ZeroBound and k = delta - arrlen
b instanceof ZeroBound and
k = delta - arrlen
)
)
)
@@ -59,4 +60,5 @@ where
k >= 0 and
if k = 0 then kstr = "" else kstr = " + " + k
select aa,
"This array access might be out of bounds, as the index might be equal to the array length" + kstr + "."
"This array access might be out of bounds, as the index might be equal to the array length" + kstr
+ "."

View File

@@ -15,23 +15,32 @@ import java
class SpecialCollectionCreation extends MethodAccess {
SpecialCollectionCreation() {
exists(Method m, RefType rt | m = this.(MethodAccess).getCallee() and rt = m.getDeclaringType() |
(rt.hasQualifiedName("java.util", "Arrays") and m.hasName("asList")) or
(rt.hasQualifiedName("java.util", "Collections") and m.getName().regexpMatch("singleton.*|unmodifiable.*"))
exists(Method m, RefType rt |
m = this.(MethodAccess).getCallee() and rt = m.getDeclaringType()
|
(rt.hasQualifiedName("java.util", "Arrays") and m.hasName("asList"))
or
(
rt.hasQualifiedName("java.util", "Collections") and
m.getName().regexpMatch("singleton.*|unmodifiable.*")
)
)
}
}
predicate containsSpecialCollection(Expr e, SpecialCollectionCreation origin) {
e = origin or
e = origin
or
exists(Variable v |
containsSpecialCollection(v.getAnAssignedValue(), origin) and
e = v.getAnAccess()
) or
)
or
exists(Call c, int i |
containsSpecialCollection(c.getArgument(i), origin) and
e = c.getCallee().getParameter(i).getAnAccess()
) or
)
or
exists(Call c, ReturnStmt r | e = c |
r.getEnclosingCallable() = c.getCallee() and
containsSpecialCollection(r.getResult(), origin)
@@ -42,15 +51,18 @@ predicate iterOfSpecialCollection(Expr e, SpecialCollectionCreation origin) {
exists(MethodAccess ma | ma = e |
containsSpecialCollection(ma.getQualifier(), origin) and
ma.getCallee().hasName("iterator")
) or
)
or
exists(Variable v |
iterOfSpecialCollection(v.getAnAssignedValue(), origin) and
e = v.getAnAccess()
) or
)
or
exists(Call c, int i |
iterOfSpecialCollection(c.getArgument(i), origin) and
e = c.getCallee().getParameter(i).getAnAccess()
) or
)
or
exists(Call c, ReturnStmt r | e = c |
r.getEnclosingCallable() = c.getCallee() and
iterOfSpecialCollection(r.getResult(), origin)

View File

@@ -11,26 +11,70 @@
* correctness
* logic
*/
import java
import semmle.code.java.Collections
predicate containerModification(string package, string type, int p, string signature, int i) {
package = "java.util" and type = "Collection" and p = 0 and signature = "remove(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Deque" and p = 0 and signature = "removeFirstOccurrence(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Deque" and p = 0 and signature = "removeLastOccurrence(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Dictionary" and p = 0 and signature = "remove(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Map" and p = 0 and signature = "remove(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Map" and p = 0 and signature = "remove(java.lang.Object,java.lang.Object)" and i = 0 or
package = "java.util" and type = "Map" and p = 1 and signature = "remove(java.lang.Object,java.lang.Object)" and i = 1 or
package = "java.util" and type = "Vector" and p = 0 and signature = "removeElement(java.lang.Object)" and i = 0
package = "java.util" and
type = "Collection" and
p = 0 and
signature = "remove(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Deque" and
p = 0 and
signature = "removeFirstOccurrence(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Deque" and
p = 0 and
signature = "removeLastOccurrence(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Dictionary" and
p = 0 and
signature = "remove(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Map" and
p = 0 and
signature = "remove(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Map" and
p = 0 and
signature = "remove(java.lang.Object,java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Map" and
p = 1 and
signature = "remove(java.lang.Object,java.lang.Object)" and
i = 1
or
package = "java.util" and
type = "Vector" and
p = 0 and
signature = "removeElement(java.lang.Object)" and
i = 0
}
class MismatchedContainerModification extends MethodAccess {
MismatchedContainerModification() {
exists(string package, string type, int i |
containerModification(package, type, _, getCallee().getSignature(), i)
|
getCallee().getDeclaringType().getASupertype*().getSourceDeclaration().hasQualifiedName(package, type) and
|
getCallee()
.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName(package, type) and
getCallee().getParameter(i).getType() instanceof TypeObject
)
}
@@ -42,7 +86,7 @@ class MismatchedContainerModification extends MethodAccess {
RefType getReceiverElementType(int i) {
exists(RefType t, GenericType g, string package, string type, int p |
containerModification(package, type, p, getCallee().getSignature(), i)
|
|
t = getCallee().getDeclaringType() and
t.getASupertype*().getSourceDeclaration() = g and
g.hasQualifiedName(package, type) and
@@ -66,5 +110,6 @@ where
elementtype = ma.getReceiverElementType(idx).getSourceDeclaration() and
argtype = ma.getArgumentType(idx) and
not haveIntersection(elementtype, argtype)
select ma.getArgument(idx), "Actual argument type '" + argtype.getName() + "'"
+ " is incompatible with expected argument type '" + elementtype.getName() + "'."
select ma.getArgument(idx),
"Actual argument type '" + argtype.getName() + "'" +
" is incompatible with expected argument type '" + elementtype.getName() + "'."

View File

@@ -30,7 +30,10 @@ where
// Every access to `v` is either...
forex(VarAccess va | va = v.getAnAccess() |
// ...an assignment storing a new container into `v`,
exists(AssignExpr assgn | va = assgn.getDest() and assgn.getSource() instanceof ClassInstanceExpr) or
exists(AssignExpr assgn |
va = assgn.getDest() and assgn.getSource() instanceof ClassInstanceExpr
)
or
// ...or a call to a mutator method on `v` such that the result of the call is not checked.
exists(ContainerMutation cm | va = cm.getQualifier() and not cm.resultIsChecked())
) and

View File

@@ -8,6 +8,7 @@
* @tags reliability
* correctness
*/
import java
from ComparisonExpr e

View File

@@ -15,7 +15,8 @@ import java
predicate comparison(BinaryExpr binop, Expr left, Expr right) {
(binop instanceof ComparisonExpr or binop instanceof EqualityTest) and
binop.getLeftOperand() = left and binop.getRightOperand() = right
binop.getLeftOperand() = left and
binop.getRightOperand() = right
}
/**
@@ -41,7 +42,8 @@ predicate varsToCompare(VarAccess left, VarAccess right, Variable v1, Variable v
predicate sameVariable(VarAccess left, VarAccess right, Variable v) {
varsToCompare(left, right, v, v) and
(
sameVariable(left.getQualifier(), right.getQualifier(), _) or
sameVariable(left.getQualifier(), right.getQualifier(), _)
or
left.isLocal() and right.isLocal()
)
}
@@ -50,8 +52,10 @@ predicate sameVariable(VarAccess left, VarAccess right, Variable v) {
predicate equal(Expr left, Expr right) {
toCompare(left, right) and
(
left.(Literal).getValue() = right.(Literal).getValue() or
sameVariable(left, right, _) or
left.(Literal).getValue() = right.(Literal).getValue()
or
sameVariable(left, right, _)
or
exists(BinaryExpr bLeft, BinaryExpr bRight | bLeft = left and bRight = right |
bLeft.getKind() = bRight.getKind() and
equal(bLeft.getLeftOperand(), bRight.getLeftOperand()) and
@@ -78,6 +82,8 @@ where
(
specialCase(comparison, equiv) and msg = "Comparison is " + equiv
or
not specialCase(comparison, _) and msg = "Comparison of identical values " + left + " and " + right and equiv=""
not specialCase(comparison, _) and
msg = "Comparison of identical values " + left + " and " + right and
equiv = ""
)
select comparison, msg + "."

View File

@@ -9,12 +9,12 @@
* @tags reliability
* correctness
*/
import java
private
predicate implementsComparable(RefType t, RefType param)
{
exists(ParameterizedType pt | t.getASupertype*() = pt and
private predicate implementsComparable(RefType t, RefType param) {
exists(ParameterizedType pt |
t.getASupertype*() = pt and
pt.getSourceDeclaration().hasQualifiedName("java.lang", "Comparable") and
param = pt.getATypeArgument() and
not param instanceof Wildcard and
@@ -22,26 +22,24 @@ predicate implementsComparable(RefType t, RefType param)
)
}
private
predicate mostSpecificComparableTypeArgument(RefType t, RefType param)
{
private predicate mostSpecificComparableTypeArgument(RefType t, RefType param) {
implementsComparable(t, param) and
not implementsComparable(t, param.getASubtype+())
}
private
predicate mostSpecificComparableTypeArgumentOrTypeObject(RefType t, RefType param)
{
private predicate mostSpecificComparableTypeArgumentOrTypeObject(RefType t, RefType param) {
if mostSpecificComparableTypeArgument(t, _)
then mostSpecificComparableTypeArgument(t, param)
else param instanceof TypeObject
then mostSpecificComparableTypeArgument(t, param)
else param instanceof TypeObject
}
private
predicate compareTo(RefType declaring, Method m, RefType param)
{
m.hasName("compareTo") and m.isPublic() and m.getNumberOfParameters() = 1 and
m.fromSource() and m.getAParamType() = param and declaring = m.getDeclaringType() and
private predicate compareTo(RefType declaring, Method m, RefType param) {
m.hasName("compareTo") and
m.isPublic() and
m.getNumberOfParameters() = 1 and
m.fromSource() and
m.getAParamType() = param and
declaring = m.getDeclaringType() and
declaring.getASupertype*().getSourceDeclaration().hasQualifiedName("java.lang", "Comparable")
}
@@ -52,5 +50,6 @@ where
actual != desired and
not compareTo(t, _, desired) and
not actual instanceof TypeVariable
select m, "The parameter of compareTo should have type '" + desired.getName()
+ "' when implementing 'Comparable<" + desired.getName() + ">'."
select m,
"The parameter of compareTo should have type '" + desired.getName() +
"' when implementing 'Comparable<" + desired.getName() + ">'."

View File

@@ -9,6 +9,7 @@
* @tags reliability
* correctness
*/
import java
from RefType t, Method equals
@@ -18,5 +19,4 @@ where
equals.hasName("equals") and
equals.getNumberOfParameters() = 1 and
not t.getAMethod() instanceof EqualsMethod
select equals,
"To override the equals method, the parameter must be of type java.lang.Object."
select equals, "To override the equals method, the parameter must be of type java.lang.Object."

View File

@@ -10,10 +10,12 @@
* @tags reliability
* correctness
*/
import java
predicate okForEquals(Class c) {
c.getAMethod() instanceof EqualsMethod or
c.getAMethod() instanceof EqualsMethod
or
(
not exists(c.getAField()) and
okForEquals(c.getASupertype())
@@ -23,7 +25,8 @@ predicate okForEquals(Class c) {
/** Holds if method `em` implements a reference equality check. */
predicate checksReferenceEquality(EqualsMethod em) {
// `java.lang.Object.equals` is the prototypical reference equality implementation.
em.getDeclaringType() instanceof TypeObject or
em.getDeclaringType() instanceof TypeObject
or
// Custom reference equality implementations observed in open-source projects.
exists(SingletonBlock blk, EQExpr eq |
blk = em.getBody() and
@@ -31,7 +34,8 @@ predicate checksReferenceEquality(EqualsMethod em) {
eq.getAnOperand().(VarAccess).getVariable() = em.getParameter(0) and
(
// `{ return (ojb==this); }`
eq = blk.getStmt().(ReturnStmt).getResult().getProperExpr() or
eq = blk.getStmt().(ReturnStmt).getResult().getProperExpr()
or
// `{ if (ojb==this) return true; else return false; }`
exists(IfStmt ifStmt | ifStmt = blk.getStmt() |
eq = ifStmt.getCondition().getProperExpr() and
@@ -39,7 +43,8 @@ predicate checksReferenceEquality(EqualsMethod em) {
ifStmt.getElse().(ReturnStmt).getResult().(BooleanLiteral).getBooleanValue() = false
)
)
) or
)
or
// Check whether `em` delegates to another method checking reference equality.
// More precisely, we check whether the body of `em` is of the form `return super.equals(o);`,
// where `o` is the (only) parameter of `em`, and the invoked method is a reference equality check.
@@ -70,9 +75,7 @@ predicate overridesDelegateEquals(EqualsMethod em, Class c) {
)
}
predicate readsOwnField(Method m) {
m.reads(m.getDeclaringType().getAField())
}
predicate readsOwnField(Method m) { m.reads(m.getDeclaringType().getAField()) }
from Class c, InstanceField f, EqualsMethod em
where
@@ -87,7 +90,5 @@ where
c.fromSource() and
not c instanceof EnumType and
not f.isFinal()
select
c, c.getName() + " inherits $@ but adds $@.",
em.getSourceDeclaration(), em.getDeclaringType().getName() + "." + em.getName(),
f, "the field " + f.getName()
select c, c.getName() + " inherits $@ but adds $@.", em.getSourceDeclaration(),
em.getDeclaringType().getName() + "." + em.getName(), f, "the field " + f.getName()

View File

@@ -9,6 +9,7 @@
* @tags reliability
* correctness
*/
import java
from MethodAccess ma, Array recvtype, Method m
@@ -19,6 +20,8 @@ where
m instanceof HashCodeMethod
or
m instanceof EqualsMethod and
haveIntersection(recvtype, (Array)ma.getArgument(0).getType())
haveIntersection(recvtype, ma.getArgument(0).getType().(Array))
)
select ma, "The " + m.getName() + " method on arrays only considers object identity and ignores array contents."
select ma,
"The " + m.getName() +
" method on arrays only considers object identity and ignores array contents."

View File

@@ -10,6 +10,7 @@
* @tags reliability
* correctness
*/
import java
predicate instanceofInEquals(EqualsMethod m, InstanceOfExpr e) {
@@ -29,6 +30,7 @@ where
exists(m.getBody()) and
m2.fromSource() and
exists(Method overridden | overridden.getSourceDeclaration() = m | m2.overrides+(overridden))
select e, "Possible violation of equals contract due to use of instanceof in $@ and/or overriding $@.",
m, m.getDeclaringType().getName() + "." + m.getName(),
m2, m2.getDeclaringType().getName() + "." + m2.getName()
select e,
"Possible violation of equals contract due to use of instanceof in $@ and/or overriding $@.", m,
m.getDeclaringType().getName() + "." + m.getName(), m2,
m2.getDeclaringType().getName() + "." + m2.getName()

Some files were not shown because too many files have changed in this diff Show More