Merge pull request #308 from aschackmull/java/autoformat-queries

Approved by yh-semmle
This commit is contained in:
semmle-qlci
2018-10-12 17:43:02 +01:00
committed by GitHub
455 changed files with 2933 additions and 2328 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,47 +9,35 @@
import UnusedMavenDependencies
/*
/**
* A whitelist of binary dependencies that should never be highlighted as unusued.
*/
predicate whitelist(Dependency d) {
/*
* jsr305 contains package annotations. If a project uses those exclusively, we will
* consider it "unused".
*/
// jsr305 contains package annotations. If a project uses those exclusively, we will
// consider it "unused".
d.getShortCoordinate() = "com.google.code.findbugs:jsr305"
}
from PomDependency d, Pom source
where
source.getADependency() = d and
/*
* There is not a Pom file for the target of this dependency, so we assume that it was resolved by
* a binary file in the local maven repository.
*/
not exists(Pom target | target = d.getPom()) and
/*
* In order to accurately identify whether this binary dependency is required, we must have identified
* a Maven repository. If we have not found a repository, it's likely that it has a custom path of
* which we are unaware, so do not report any problems.
*/
exists(MavenRepo mr) and
/*
* We either haven't indexed a relevant jar file, which suggests that nothing statically depended upon
* it, or we have indexed the relevant jar file, but no source code in the project defined by the pom
* depends on any code within the detected jar.
*/
not pomDependsOnContainer(source, d.getJar()) and
/*
* If something that depends on us depends on the jar represented by this dependency, and it doesn't
* depend directly on the jar itself, we don't consider it to be "unused".
*/
not exists(Pom pomThatDependsOnSource |
pomThatDependsOnSource.getAnExportedPom+() = source
|
pomDependsOnContainer(pomThatDependsOnSource, d.getJar()) and
not exists(File f | f = pomThatDependsOnSource.getADependency().getJar() and f = d.getJar())) and
// Filter out those dependencies on the whitelist
not whitelist(d)
source.getADependency() = d and
// There is not a Pom file for the target of this dependency, so we assume that it was resolved by
// a binary file in the local maven repository.
not exists(Pom target | target = d.getPom()) and
// In order to accurately identify whether this binary dependency is required, we must have identified
// a Maven repository. If we have not found a repository, it's likely that it has a custom path of
// which we are unaware, so do not report any problems.
exists(MavenRepo mr) and
// We either haven't indexed a relevant jar file, which suggests that nothing statically depended upon
// it, or we have indexed the relevant jar file, but no source code in the project defined by the pom
// depends on any code within the detected jar.
not pomDependsOnContainer(source, d.getJar()) and
// If something that depends on us depends on the jar represented by this dependency, and it doesn't
// depend directly on the jar itself, we don't consider it to be "unused".
not exists(Pom pomThatDependsOnSource | pomThatDependsOnSource.getAnExportedPom+() = source |
pomDependsOnContainer(pomThatDependsOnSource, d.getJar()) and
not exists(File f | f = pomThatDependsOnSource.getADependency().getJar() and f = d.getJar())
) and
// Filter out those dependencies on the whitelist
not whitelist(d)
select d, "Maven dependency on the binary package " + d.getShortCoordinate() + " is unused."

View File

@@ -13,22 +13,16 @@ import UnusedMavenDependencies
from PomDependency d, Pom source, Pom target
where
source.getADependency() = d and
/*
* We have a targetPom file, so this is a "source" dependency, rather than a binary dependency
* from the Maven repository. Note, although .pom files exist in the local maven repository, they
* are usually not indexed because they are outside the source directory. We assume that they have
* not been indexed.
*/
target = d.getPom() and
/*
* If we have a pom for the target of this dependency, then it is unused iff neither it, nor any
* of its transitive dependencies are required.
*/
not exists(Pom exported |
exported = target.getAnExportedPom*()
|
pomDependsOnContainer(source, exported.getAnExportedDependency().getJar()) or
pomDependsOnPom(source, exported)
)
source.getADependency() = d and
// We have a targetPom file, so this is a "source" dependency, rather than a binary dependency
// from the Maven repository. Note, although .pom files exist in the local maven repository, they
// are usually not indexed because they are outside the source directory. We assume that they have
// not been indexed.
target = d.getPom() and
// If we have a pom for the target of this dependency, then it is unused iff neither it, nor any
// of its transitive dependencies are required.
not exists(Pom exported | exported = target.getAnExportedPom*() |
pomDependsOnContainer(source, exported.getAnExportedDependency().getJar()) or
pomDependsOnPom(source, exported)
)
select d, "Maven dependency onto " + d.getShortCoordinate() + " is unused."

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,27 +9,28 @@
* useless-code
* external/cwe/cwe-561
*/
import semmle.code.java.deadcode.DeadCode
from DeadClass c, Element origin, string reason
where
if exists(DeadRoot root | root = c.getADeadRoot() | not root = c.getACallable()) then (
// Report a list of the dead roots.
origin = c.getADeadRoot() and
not origin = c.getACallable() and
// There are uses of this class from outside the class.
reason = " is only used from dead code originating at $@."
if exists(DeadRoot root | root = c.getADeadRoot() | not root = c.getACallable())
then (
// Report a list of the dead roots.
origin = c.getADeadRoot() and
not origin = c.getACallable() and
// There are uses of this class from outside the class.
reason = " is only used from dead code originating at $@."
) else (
// There are no dead roots outside this class.
origin = c and
if c.isUnusedOutsideClass() then
if c.isUnusedOutsideClass()
then
// Never accessed outside this class, so it's entirely unused.
reason = " is entirely unused."
else
/*
* There are no dead roots outside the class, but the class has a possible liveness cause
* external to the class, so it must be accessed from at least one dead-code cycle.
*/
// There are no dead roots outside the class, but the class has a possible liveness cause
// external to the class, so it must be accessed from at least one dead-code cycle.
reason = " is only used from or in a dead-code cycle."
)
select c, "The class " + c.getName() + reason, origin, origin.getName()

View File

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

View File

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

View File

@@ -9,6 +9,7 @@
* @tags maintainability
* external/cwe/cwe-561
*/
import java
import semmle.code.java.deadcode.DeadCode
@@ -16,35 +17,42 @@ from File f, int n
where
n =
// Lines of code contributed by dead classes.
sum(DeadClass deadClass | deadClass.getFile() = f |
deadClass.getNumberOfLinesOfCode() -
/*
* Remove inner and local classes, as they are reported as separate dead classes. Do not
* remove anonymous classes, because they aren't reported separately.
*/
sum(NestedClass innerClass | innerClass.getEnclosingType() = deadClass and not innerClass.isAnonymous() |
innerClass.getNumberOfLinesOfCode()
sum(DeadClass deadClass |
deadClass.getFile() = f
|
deadClass.getNumberOfLinesOfCode() -
// Remove inner and local classes, as they are reported as separate dead classes. Do not
// remove anonymous classes, because they aren't reported separately.
sum(NestedClass innerClass |
innerClass.getEnclosingType() = deadClass and not innerClass.isAnonymous()
|
innerClass.getNumberOfLinesOfCode()
)
) +
// Lines of code contributed by dead methods, not in dead classes.
sum(DeadMethod deadMethod |
deadMethod.getFile() = f and not deadMethod.isInDeadScope()
|
deadMethod.getNumberOfLinesOfCode() -
// Remove local classes defined in the dead method - they are reported separately as a dead
// class. We keep anonymous class counts, because anonymous classes are not reported
// separately.
sum(LocalClass localClass |
localClass.getLocalClassDeclStmt().getEnclosingCallable() = deadMethod
|
localClass.getNumberOfLinesOfCode()
)
) +
// Lines of code contributed by dead fields, not in dead classes.
sum(DeadField deadField |
deadField.getFile() = f and not deadField.isInDeadScope()
|
deadField.getNumberOfLinesOfCode()
) +
// Lines of code contributed by unused enum constants.
sum(UnusedEnumConstant deadEnumConstant |
deadEnumConstant.getFile() = f
|
deadEnumConstant.getNumberOfLinesOfCode()
)
) +
// Lines of code contributed by dead methods, not in dead classes.
sum(DeadMethod deadMethod | deadMethod.getFile() = f and not deadMethod.isInDeadScope() |
deadMethod.getNumberOfLinesOfCode() -
/*
* Remove local classes defined in the dead method - they are reported separately as a dead
* class. We keep anonymous class counts, because anonymous classes are not reported
* separately.
*/
sum(LocalClass localClass | localClass.getLocalClassDeclStmt().getEnclosingCallable() = deadMethod |
localClass.getNumberOfLinesOfCode()
)
) +
// Lines of code contributed by dead fields, not in dead classes.
sum(DeadField deadField | deadField.getFile() = f and not deadField.isInDeadScope() |
deadField.getNumberOfLinesOfCode()
) +
// Lines of code contributed by unused enum constants.
sum(UnusedEnumConstant deadEnumConstant | deadEnumConstant.getFile() = f |
deadEnumConstant.getNumberOfLinesOfCode()
)
select f, n
order by n desc
select f, n order by n desc

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -37,12 +37,8 @@ class InstanceFieldWrite extends FieldWrite {
*/
class ImpureStmt extends Stmt {
ImpureStmt() {
exists(Expr e |
e.getEnclosingStmt() = this
|
/*
* Only permit calls to set of whitelisted targets.
*/
exists(Expr e | e.getEnclosingStmt() = this |
// Only permit calls to set of whitelisted targets.
(
e instanceof Call and
not e.(Call).getCallee().getDeclaringType().hasQualifiedName("java.util", "Collections")
@@ -59,12 +55,12 @@ class ImpureStmt extends Stmt {
*/
private Stmt getANestedStmt(Block block) {
// Any non-block statement
not result instanceof Block and result = block.getAStmt() or
not result instanceof Block and result = block.getAStmt()
or
// Or any statement nested in a block
result = getANestedStmt(block.getAStmt())
}
/**
* A class whose loading and construction by Spring does not have any side-effects outside the class.
*
@@ -73,16 +69,10 @@ private Stmt getANestedStmt(Block block) {
class SpringPureClass extends Class {
SpringPureClass() {
(
/*
* The only permitted statement in static initializers is the initialization of a static
* final or effectively final logger fields, or effectively immutable types.
*/
forall(Stmt s |
s = getANestedStmt(getAMember().(StaticInitializer).getBody())
|
exists(Field f |
f = s.(ExprStmt).getExpr().(AssignExpr).getDest().(FieldWrite).getField()
|
// The only permitted statement in static initializers is the initialization of a static
// final or effectively final logger fields, or effectively immutable types.
forall(Stmt s | s = getANestedStmt(getAMember().(StaticInitializer).getBody()) |
exists(Field f | f = s.(ExprStmt).getExpr().(AssignExpr).getDest().(FieldWrite).getField() |
(
// A logger field
f.getName().toLowerCase() = "logger" or
@@ -92,11 +82,7 @@ class SpringPureClass extends Class {
) and
f.isStatic() and
// Only written to in this statement e.g. final or effectively final
forall(FieldWrite fw |
fw = f.getAnAccess()
|
fw.getEnclosingStmt() = s
)
forall(FieldWrite fw | fw = f.getAnAccess() | fw.getEnclosingStmt() = s)
)
)
) and
@@ -107,20 +93,23 @@ class SpringPureClass extends Class {
c = getAMember()
) and
impureStmt.getEnclosingCallable() = c
|
c instanceof InstanceInitializer or
c instanceof Constructor or
|
c instanceof InstanceInitializer
or
c instanceof Constructor
or
// afterPropertiesSet() method called after bean initialization
c = this.(InitializingBeanClass).getAfterPropertiesSet() or
c = this.(InitializingBeanClass).getAfterPropertiesSet()
or
// Init and setter methods must be pure, because they are called when the bean is initialized
exists(SpringBean bean |
this = bean.getClass()
|
exists(SpringBean bean | this = bean.getClass() |
c = bean.getInitMethod() or
c = bean.getAProperty().getSetterMethod()
) or
)
or
// Setter method by autowiring, either in the XML or by annotation
c = this.getAMethod().(SpringBeanAutowiredCallable) or
c = this.getAMethod().(SpringBeanAutowiredCallable)
or
c = this.getAMethod().(SpringBeanXMLAutowiredSetterMethod)
)
}
@@ -134,7 +123,6 @@ class SpringBeanFactory extends ClassOrInterface {
getAnAncestor().hasQualifiedName("org.springframework.beans.factory", "BeanFactory")
}
/**
* Get a bean constructed by a call to this bean factory.
*/
@@ -143,7 +131,7 @@ class SpringBeanFactory extends ClassOrInterface {
getBean.hasName("getBean") and
call.getMethod() = getBean and
getBean.getDeclaringType() = this
|
|
result.getBeanIdentifier() = call.getArgument(0).(CompileTimeConstantExpr).getStringValue()
)
}
@@ -162,13 +150,12 @@ class LiveSpringBean extends SpringBean {
not isLazyInit() and
// or has no side-effects when constructed
not getClass() instanceof SpringPureClass
) or
)
or
(
/*
* If the class does not exist for this bean, or the class is not a source bean, then this is
* likely to be a definition using a library class, in which case we should consider it to be
* live.
*/
// If the class does not exist for this bean, or the class is not a source bean, then this is
// likely to be a definition using a library class, in which case we should consider it to be
// live.
not exists(getClass()) or
not getClass().fromSource() or
// In alfresco, "webscript" beans should be considered live
@@ -176,43 +163,45 @@ class LiveSpringBean extends SpringBean {
// A live child bean implies this bean is live
exists(LiveSpringBean child | this = child.getBeanParent()) or
// Beans constructed by a bean factory are considered live
exists(SpringBeanFactory beanFactory |
this = beanFactory.getAConstructedBean()
)
) or
exists(SpringBeanFactory beanFactory | this = beanFactory.getAConstructedBean())
)
or
(
// Referenced by a live bean, either as a property or argument in the XML
exists(LiveSpringBean other |
this = other.getAConstructorArg().getArgRefBean() or
this = other.getAProperty().getPropertyRefBean()
) or
)
or
// Referenced as a factory bean
exists(LiveSpringBean springBean |
this = springBean.getFactoryBean()
) or
exists(LiveSpringBean springBean | this = springBean.getFactoryBean())
or
// Injected by @Autowired annotation
exists(SpringBeanAutowiredCallable autowiredCallable |
// The callable must be in a live class
autowiredCallable.getEnclosingSpringBean() instanceof LiveSpringBean or
autowiredCallable.getEnclosingSpringComponent().isLive()
|
|
// This bean is injected into it
this = autowiredCallable.getAnInjectedBean()
) or
)
or
// Injected by @Autowired annotation on field
exists(SpringBeanAutowiredField autowiredField |
// The field must be in a live class
autowiredField.getEnclosingSpringBean() instanceof LiveSpringBean or
autowiredField.getEnclosingSpringComponent().isLive()
|
|
// This bean is injected into it
this = autowiredField.getInjectedBean()
) or
)
or
// Injected by autowired specified in XML
exists(SpringBeanXMLAutowiredSetterMethod setterMethod |
// The config method must be on a live bean
setterMethod.getDeclaringType().(SpringBeanRefType).getSpringBean() instanceof LiveSpringBean
|
setterMethod.getDeclaringType().(SpringBeanRefType).getSpringBean() instanceof
LiveSpringBean
|
// This bean is injected into it
this = setterMethod.getInjectedBean()
)
@@ -224,9 +213,7 @@ class LiveSpringBean extends SpringBean {
* A `SpringBean` that can be safely removed from the program without changing overall behavior.
*/
class UnusedSpringBean extends SpringBean {
UnusedSpringBean() {
not this instanceof LiveSpringBean
}
UnusedSpringBean() { not this instanceof LiveSpringBean }
}
from UnusedSpringBean unused

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,31 +11,100 @@
* correctness
* logic
*/
import java
import semmle.code.java.Collections
predicate containerAccess(string package, string type, int p, string signature, int i) {
package = "java.util" and type = "Collection" and p = 0 and signature = "contains(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Dictionary" and p = 0 and signature = "get(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Hashtable" and p = 1 and signature = "contains(java.lang.Object)" and i = 0 or
package = "java.util" and type = "List" and p = 0 and signature = "indexOf(java.lang.Object)" and i = 0 or
package = "java.util" and type = "List" and p = 0 and signature = "lastIndexOf(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Map" and p = 0 and signature = "get(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Map" and p = 0 and signature = "getOrDefault(java.lang.Object,java.lang.Object)" and i = 0 or
package = "java.util" and type = "Map" and p = 0 and signature = "containsKey(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Map" and p = 1 and signature = "containsValue(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Stack" and p = 0 and signature = "search(java.lang.Object)" and i = 0 or
package = "java.util" and type = "Vector" and p = 0 and signature = "indexOf(java.lang.Object,int)" and i = 0 or
package = "java.util" and type = "Vector" and p = 0 and signature = "lastIndexOf(java.lang.Object,int)" and i = 0 or
package = "java.util.concurrent" and type = "ConcurrentHashMap" and p = 1 and signature = "contains(java.lang.Object)" and i = 0
package = "java.util" and
type = "Collection" and
p = 0 and
signature = "contains(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Dictionary" and
p = 0 and
signature = "get(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Hashtable" and
p = 1 and
signature = "contains(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "List" and
p = 0 and
signature = "indexOf(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "List" and
p = 0 and
signature = "lastIndexOf(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Map" and
p = 0 and
signature = "get(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Map" and
p = 0 and
signature = "getOrDefault(java.lang.Object,java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Map" and
p = 0 and
signature = "containsKey(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Map" and
p = 1 and
signature = "containsValue(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Stack" and
p = 0 and
signature = "search(java.lang.Object)" and
i = 0
or
package = "java.util" and
type = "Vector" and
p = 0 and
signature = "indexOf(java.lang.Object,int)" and
i = 0
or
package = "java.util" and
type = "Vector" and
p = 0 and
signature = "lastIndexOf(java.lang.Object,int)" and
i = 0
or
package = "java.util.concurrent" and
type = "ConcurrentHashMap" and
p = 1 and
signature = "contains(java.lang.Object)" and
i = 0
}
class MismatchedContainerAccess extends MethodAccess {
MismatchedContainerAccess() {
exists(string package, string type, int i |
containerAccess(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
)
}
@@ -47,7 +116,7 @@ class MismatchedContainerAccess extends MethodAccess {
RefType getReceiverElementType(int i) {
exists(RefType t, GenericType g, string package, string type, int p |
containerAccess(package, type, p, getCallee().getSignature(), i)
|
|
t = getCallee().getDeclaringType() and
t.getASupertype*().getSourceDeclaration() = g and
g.hasQualifiedName(package, type) and
@@ -71,5 +140,6 @@ where
typearg = ma.getReceiverElementType(idx).getSourceDeclaration() and
argtype = ma.getArgumentType(idx) and
not haveIntersection(typearg, argtype)
select ma.getArgument(idx), "Actual argument type '" + argtype.getName() + "'"
+ " is incompatible with expected argument type '" + typearg.getName() + "'."
select ma.getArgument(idx),
"Actual argument type '" + argtype.getName() + "'" +
" is incompatible with expected argument type '" + typearg.getName() + "'."

View File

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

View File

@@ -26,11 +26,15 @@ where
// Every access to `v` is either...
forall(VarAccess va | va = v.getAnAccess() |
// ...an assignment storing a fresh container into `v`,
exists(AssignExpr assgn | va = assgn.getDest() | assgn.getSource() instanceof FreshContainer) or
/// ...a return (but only if `v` is a local variable)
(v instanceof LocalVariableDecl and exists(ReturnStmt ret | ret.getResult() = va)) or
exists(AssignExpr assgn | va = assgn.getDest() | assgn.getSource() instanceof FreshContainer)
or
// ...a return (but only if `v` is a local variable)
(v instanceof LocalVariableDecl and exists(ReturnStmt ret | ret.getResult() = va))
or
// ...or a call to a query method on `v`.
exists(MethodAccess ma | va = ma.getQualifier() | ma.getMethod() instanceof ContainerQueryMethod)
exists(MethodAccess ma | va = ma.getQualifier() |
ma.getMethod() instanceof ContainerQueryMethod
)
) and
// There is at least one call to a query method.
exists(MethodAccess ma | v.getAnAccess() = ma.getQualifier() |

View File

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

View File

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

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