mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Java: Autoformat most queries.
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/non-private-field
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.JDKAnnotations
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/undocumented-parameter
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
import JavadocCommon
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/undocumented-return-value
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
import JavadocCommon
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/undocumented-type
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
import JavadocCommon
|
||||
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/use-of-clone-method
|
||||
* @tags reliability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
class ObjectCloneMethod extends Method {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/override-of-clone-method
|
||||
* @tags reliability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
class ObjectCloneMethod extends Method {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/use-of-cloneable-interface
|
||||
* @tags reliability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from RefType t
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @id java/override-of-finalize-method
|
||||
* @tags reliability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
class ObjectFinalizeMethod extends Method {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @id java/misnamed-constant
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
import NamingConventionsCommon
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @id java/misnamed-function
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from Method m
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @id java/misnamed-type
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from RefType t
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @id java/misnamed-variable
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
import NamingConventionsCommon
|
||||
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/raw-constructor-invocation
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from ClassInstanceExpr cie
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/raw-return-type
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from Method m
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/raw-variable
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from Variable v
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @id java/underscore-identifier
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
class IdentifierElement extends Element {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* testability
|
||||
* complexity
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
class ComplexStmt extends Stmt {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @tags testability
|
||||
* readability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
predicate nontrivialLogicalOperator(BinaryExpr e) {
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* useless-code
|
||||
* external/cwe/cwe-561
|
||||
*/
|
||||
|
||||
import semmle.code.java.deadcode.DeadCode
|
||||
|
||||
from RootdefCallable c
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() + " $@"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @tags maintainability
|
||||
* frameworks/spring
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.Spring
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @tags maintainability
|
||||
* frameworks/spring
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.Spring
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* @tags maintainability
|
||||
* frameworks/spring
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.Spring
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
* @tags maintainability
|
||||
* frameworks/spring
|
||||
*/
|
||||
import java
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.Spring
|
||||
|
||||
from SpringImport i
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* maintainability
|
||||
* frameworks/spring
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.Spring
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* @tags maintainability
|
||||
* frameworks/spring
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.Spring
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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?"
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() + "."
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* @tags maintainability
|
||||
* correctness
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from MulExpr e
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* @tags maintainability
|
||||
* correctness
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from IntegerLiteral lit, string val
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* @tags reliability
|
||||
* maintainability
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from Class t, TypeCloneable cloneable
|
||||
|
||||
@@ -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
|
||||
+ "."
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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() + "'."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @tags reliability
|
||||
* correctness
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
from ComparisonExpr e
|
||||
|
||||
@@ -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 + "."
|
||||
|
||||
@@ -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() + ">'."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user