Merge master into next.

Conflict in `cpp/ql/test/library-tests/sideEffects/functions/sideEffects.expected`,
resolved by accepting test output (combining changes).
This commit is contained in:
Aditya Sharad
2018-12-12 17:22:16 +00:00
345 changed files with 9800 additions and 2436 deletions

View File

@@ -49,9 +49,9 @@ class DocuCallable extends Callable {
predicate hasAcceptableDocText() { acceptableDocText(this.getDoc().getJavadoc()) }
string toMethodOrConstructorString() {
(this instanceof Method and result = "method")
this instanceof Method and result = "method"
or
(this instanceof Constructor and result = "constructor")
this instanceof Constructor and result = "constructor"
}
}

View File

@@ -15,7 +15,7 @@ where
callable.(Documentable).getJavadoc().getAChild() = paramTag and
(if callable instanceof Constructor then what = "constructor" else what = "method") and
if exists(paramTag.getParamName())
then (
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.
@@ -24,7 +24,7 @@ where
) and
msg = "@param tag \"" + paramTag.getParamName() + "\" does not match any actual parameter of " +
what + " \"" + callable.getName() + "()\"."
) else
else
// The tag has no value at all.
msg = "This @param tag does not have a value."
select paramTag, msg

View File

@@ -127,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

@@ -39,13 +39,11 @@ class ImpureStmt extends Stmt {
ImpureStmt() {
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")
)
e instanceof Call and
not e.(Call).getCallee().getDeclaringType().hasQualifiedName("java.util", "Collections")
or
// Writing to a field that is not an instance field is a no-no
(e instanceof FieldWrite and not e instanceof InstanceFieldWrite)
e instanceof FieldWrite and not e instanceof InstanceFieldWrite
)
}
}
@@ -68,22 +66,20 @@ 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() |
(
// A logger field
f.getName().toLowerCase() = "logger" or
f.getName().toLowerCase() = "log" or
// An immutable type
f.getType() instanceof ImmutableType
) 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)
)
// 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
f.getName().toLowerCase() = "log" or
// An immutable type
f.getType() instanceof ImmutableType
) 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)
)
) and
// No constructor, instance initializer or Spring bean init or setter method that is impure.
@@ -145,12 +141,10 @@ class SpringBeanFactory extends ClassOrInterface {
class LiveSpringBean extends SpringBean {
LiveSpringBean() {
// Must not be needed for side effects due to construction
(
// Only loaded by the container when required, so construction cannot have any useful side-effects
not isLazyInit() and
// or has no side-effects when constructed
not getClass() instanceof SpringPureClass
)
// Only loaded by the container when required, so construction cannot have any useful side-effects
not isLazyInit() and
// or has no side-effects when constructed
not getClass() instanceof SpringPureClass
or
(
// If the class does not exist for this bean, or the class is not a source bean, then this is

View File

@@ -14,9 +14,6 @@ import java
from EmptyStmt empty, string action
where
if exists(LoopStmt l | l.getBody() = empty)
then (
action = "turned into '{}'"
) else (
action = "deleted"
)
then action = "turned into '{}'"
else action = "deleted"
select empty, "This empty statement should be " + action + "."

View File

@@ -27,7 +27,7 @@ RefType aTypeVisibleFrom(TypeVariable var) {
result = i.getImportedType()
)
or
(var.getPackage() = result.getPackage() and result instanceof TopLevelType)
var.getPackage() = result.getPackage() and result instanceof TopLevelType
}
from RefType hidden, TypeVariable var

View File

@@ -21,10 +21,8 @@ predicate iteratorWrapper(Iterable it, Field f, boolean wrap) {
(
f.isFinal()
or
(
strictcount(f.getAnAssignedValue()) = 1 and
f.getAnAssignedValue().getEnclosingCallable() instanceof InitializerMethod
)
strictcount(f.getAnAssignedValue()) = 1 and
f.getAnAssignedValue().getEnclosingCallable() instanceof InitializerMethod
) and
// ... whose type is a sub-type of `java.util.Iterator` and ...
f

View File

@@ -12,7 +12,7 @@
import java
int integralTypeWidth(IntegralType t) {
if (t.hasName("long") or t.hasName("Long")) then result = 64 else result = 32
if t.hasName("long") or t.hasName("Long") then result = 64 else result = 32
}
int eval(Expr e) { result = e.(CompileTimeConstantExpr).getIntValue() }

View File

@@ -71,26 +71,24 @@ class AssocNestedExpr extends BinaryExpr {
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)
this instanceof EqualityTest and parent instanceof EqualityTest
or
// (x*y)/z = x*(y/z)
(this instanceof MulExpr and parent instanceof DivExpr and idx = 0)
this instanceof MulExpr and parent instanceof DivExpr and idx = 0
or
// (x/y)%z = x/(y%z)
(this instanceof DivExpr and parent instanceof RemExpr and idx = 0)
this instanceof DivExpr and parent instanceof RemExpr and idx = 0
or
// (x+y)-z = x+(y-z)
(this instanceof AddExpr and parent instanceof SubExpr and idx = 0)
this instanceof AddExpr and parent instanceof SubExpr and idx = 0
)
}
}
@@ -102,12 +100,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)
parent instanceof LogicalExpr and this instanceof RelationExpr
)
}
}

View File

@@ -18,12 +18,10 @@ class SpecialCollectionCreation extends MethodAccess {
exists(Method m, RefType rt |
m = this.(MethodAccess).getCallee() and rt = m.getDeclaringType()
|
(rt.hasQualifiedName("java.util", "Arrays") and m.hasName("asList"))
rt.hasQualifiedName("java.util", "Arrays") and m.hasName("asList")
or
(
rt.hasQualifiedName("java.util", "Collections") and
m.getName().regexpMatch("singleton.*|unmodifiable.*")
)
rt.hasQualifiedName("java.util", "Collections") and
m.getName().regexpMatch("singleton.*|unmodifiable.*")
)
}
}

View File

@@ -29,7 +29,7 @@ where
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))
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() |

View File

@@ -16,10 +16,8 @@ import java
predicate okForEquals(Class c) {
c.getAMethod() instanceof EqualsMethod
or
(
not exists(c.getAField()) and
okForEquals(c.getASupertype())
)
not exists(c.getAField()) and
okForEquals(c.getASupertype())
}
/** Holds if method `em` implements a reference equality check. */

View File

@@ -0,0 +1,8 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="DoubleCheckedLockingShared.qhelp" />
</qhelp>

View File

@@ -0,0 +1,23 @@
/**
* @name Double-checked locking is not thread-safe
* @description A repeated check on a non-volatile field is not thread-safe, and
* could result in unexpected behavior.
* @kind problem
* @problem.severity error
* @precision high
* @id java/unsafe-double-checked-locking
* @tags reliability
* correctness
* concurrency
* external/cwe/cwe-609
*/
import java
import DoubleCheckedLocking
from IfStmt if1, IfStmt if2, SynchronizedStmt sync, Field f
where
doubleCheckedLocking(if1, if2, sync, f) and
not f.isVolatile()
select sync, "Double-checked locking on the non-volatile field $@ is not thread-safe.", f,
f.toString()

View File

@@ -0,0 +1,43 @@
import java
import semmle.code.java.dataflow.SSA
/**
* Gets a read of `f`. Gets both direct reads and indirect reads through
* assignment to a local variable.
*/
private Expr getAFieldRead(Field f) {
result = f.getAnAccess()
or
exists(SsaExplicitUpdate v | v.getSourceVariable().getVariable() instanceof LocalScopeVariable |
result = v.getAUse() and
v.getDefiningExpr().(VariableAssign).getSource() = getAFieldRead(f)
)
or
result.(ParExpr).getExpr() = getAFieldRead(f)
or
result.(AssignExpr).getSource() = getAFieldRead(f)
}
/**
* Gets an expression that corresponds to `f == null`, either directly testing
* `f` or indirectly through a local variable `(x = f) == null`.
*/
private Expr getANullCheck(Field f) {
exists(EqualityTest eq | eq.polarity() = true |
eq.hasOperands(any(NullLiteral nl), getAFieldRead(f)) and
result = eq
)
}
/**
* Holds if the sequence `if1`-`sync`-`if2` corresponds to a double-checked
* locking pattern for the field `f`. Fields with immutable types are excluded,
* as they are always safe to initialize with double-checked locking.
*/
predicate doubleCheckedLocking(IfStmt if1, IfStmt if2, SynchronizedStmt sync, Field f) {
if1.getThen() = sync.getParent*() and
sync.getBlock() = if2.getParent*() and
if1.getCondition() = getANullCheck(f) and
if2.getCondition() = getANullCheck(f) and
not f.getType() instanceof ImmutableType
}

View File

@@ -0,0 +1,13 @@
private Object lock = new Object();
private MyObject f = null;
public MyObject getMyObject() {
if (f == null) {
synchronized(lock) {
if (f == null) {
f = new MyObject(); // BAD
}
}
}
return f;
}

View File

@@ -0,0 +1,14 @@
private Object lock = new Object();
private volatile MyObject f = null;
public MyObject getMyObject() {
if (f == null) {
synchronized(lock) {
if (f == null) {
f = new MyObject();
f.init(); // BAD
}
}
}
return f;
}

View File

@@ -0,0 +1,17 @@
private Object lock = new Object();
private volatile MyObject f = null;
public MyObject getMyObject() {
MyObject result = f;
if (result == null) {
synchronized(lock) {
result = f;
if (result == null) {
result = new MyObject();
result.init();
f = result; // GOOD
}
}
}
return result;
}

View File

@@ -0,0 +1,86 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Double-checked locking is a common pattern for lazy initialization of a field
accessed by multiple threads.
Depending on the memory model of the underlying runtime, it can, however, be
quite difficult to implement correctly, since reorderings performed by
compiler, runtime, or CPU might expose un-initialized or half-way initialized
objects to other threads.
Java has since version 5 improved its memory model to support double-checked
locking if the underlying field is marked <code>volatile</code> and if all
initialization happens before the volatile write.
</p>
</overview>
<recommendation>
<p>
First, it should be considered whether the getter that performs the lazy
initialization is performance critical.
If not, a much simpler solution is to completely avoid double-checked locking
and simply mark the entire getter as <code>synchronized</code>.
This is much easier to get right and guards against hard-to-find concurrency bugs.
</p>
<p>
If double-checked locking is used, it is important that the underlying field is
<code>volatile</code> and that the update to the field is the last thing that
happens in the synchronized region, that is, all initialization must be done
before the field is assigned.
Furthermore, the Java version must be 5 or newer.
Reading a <code>volatile</code> field has a slight overhead, so it is also
useful to use a local variable to minimize the number of volatile reads.
</p>
</recommendation>
<example>
<p>
The following code lazily initializes <code>f</code> to <code>new MyObject()</code>.
</p>
<sample src="DoubleCheckedLockingBad1.java"/>
<p>
This code is not thread-safe as another thread might see the assignment to
<code>f</code> before the constructor finishes evaluating, for example if the
compiler inlines the memory allocation and the constructor and reorders the
assignment to <code>f</code> to occur just after the memory allocation.
</p>
<p>
Another example that also is not thread-safe, even when <code>volatile</code>
is used, is if additional initialization happens after the assignment to
<code>f</code>, since then other threads may access the constructed object
before it is fully initialized, even without any reorderings by the compiler or
runtime.
</p>
<sample src="DoubleCheckedLockingBad2.java"/>
<p>
The code above should be rewritten to both use <code>volatile</code> and finish
all initialization before <code>f</code> is updated. Additionally, a local
variable can be used to avoid reading the field more times than neccessary.
</p>
<sample src="DoubleCheckedLockingGood.java"/>
</example>
<references>
<li>
<a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">The "Double-Checked Locking is Broken" Declaration</a>.
</li>
<li>
Java Language Specification:
<a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">17.4. Memory Model</a>.
</li>
<li>
Wikipedia: <a href="https://en.wikipedia.org/wiki/Double-checked_locking">Double-checked locking</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,8 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="DoubleCheckedLockingShared.qhelp" />
</qhelp>

View File

@@ -0,0 +1,43 @@
/**
* @name Race condition in double-checked locking object initialization
* @description Performing additional initialization on an object after
* assignment to a shared variable guarded by double-checked
* locking is not thread-safe, and could result in unexpected
* behavior.
* @kind problem
* @problem.severity warning
* @precision high
* @id java/unsafe-double-checked-locking-init-order
* @tags reliability
* correctness
* concurrency
* external/cwe/cwe-609
*/
import java
import DoubleCheckedLocking
predicate whitelistedMethod(Method m) {
m.getDeclaringType().hasQualifiedName("java.io", _) and
m.hasName("println")
}
class SideEffect extends Expr {
SideEffect() {
this instanceof MethodAccess and
not whitelistedMethod(this.(MethodAccess).getMethod())
or
this.(Assignment).getDest() instanceof FieldAccess
}
}
from IfStmt if1, IfStmt if2, SynchronizedStmt sync, Field f, AssignExpr a, SideEffect se
where
doubleCheckedLocking(if1, if2, sync, f) and
a.getEnclosingStmt().getParent*() = if2.getThen() and
se.getEnclosingStmt().getParent*() = sync.getBlock() and
a.(ControlFlowNode).getASuccessor+() = se and
a.getDest().(FieldAccess).getField() = f
select a,
"Potential race condition. This assignment to $@ is visible to other threads before the subsequent statements are executed.",
f, f.toString()

View File

@@ -25,16 +25,12 @@ class ThreadClass extends Class {
(
result.getNumberOfParameters() = 0
or
(
result.getNumberOfParameters() = 1 and
result.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "String")
)
result.getNumberOfParameters() = 1 and
result.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "String")
or
(
result.getNumberOfParameters() = 2 and
result.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "ThreadGroup") and
result.getParameter(1).getType().(RefType).hasQualifiedName("java.lang", "String")
)
result.getNumberOfParameters() = 2 and
result.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "ThreadGroup") and
result.getParameter(1).getType().(RefType).hasQualifiedName("java.lang", "String")
)
}

View File

@@ -28,7 +28,7 @@ predicate locallySynchronized(MethodAccess ma) {
}
predicate hasUnsynchronizedCall(Method m) {
(m.isPublic() and not m.isSynchronized())
m.isPublic() and not m.isSynchronized()
or
exists(MethodAccess ma, Method caller |
ma.getMethod() = m and caller = ma.getEnclosingCallable()

View File

@@ -94,17 +94,14 @@ where
exists(IfStmt unsyncNullCheck | unsyncNullCheck = init.getAnEnclosingNullCheck() |
not unsyncNullCheck.getParent+() instanceof ValidSynchStmt
) and
if (i.getParent+() instanceof ValidSynchStmt)
if i.getParent+() instanceof ValidSynchStmt
then (
not init.getField().isVolatile() and
message = "The field must be volatile."
) else (
if (i.getParent+() instanceof SynchronizedStmt)
then (
message = "Bad synchronization."
) else (
message = "Missing synchronization."
)
if i.getParent+() instanceof SynchronizedStmt
then message = "Bad synchronization."
else message = "Missing synchronization."
)
select init, "Incorrect lazy initialization of static field $@: " + message, init.getField() as f,
f.getName()

View File

@@ -47,11 +47,9 @@ class MethodRequiresSynch extends Method {
private predicate synchronizedCallable(Callable c) {
c.isSynchronized()
or
(
c.isPrivate() and
forall(MethodAccess parent | parent.getCallee() = c |
synchronizedThisAccess(parent, c.getDeclaringType())
)
c.isPrivate() and
forall(MethodAccess parent | parent.getCallee() = c |
synchronizedThisAccess(parent, c.getDeclaringType())
)
}

View File

@@ -56,33 +56,25 @@ private predicate comparisonOfContainerSizeToZero(
BinaryExpr e, string containerKind, string trueOrFalse
) {
exists(Expr l, Expr r | l = e.getLeftOperand() and r = e.getRightOperand() |
(
e instanceof LTExpr and
l.(SizeOfContainer).getContainerKind() = containerKind and
r instanceof IntegralZeroLiteral and
trueOrFalse = "false"
)
e instanceof LTExpr and
l.(SizeOfContainer).getContainerKind() = containerKind and
r instanceof IntegralZeroLiteral and
trueOrFalse = "false"
or
(
e instanceof GTExpr and
l instanceof IntegralZeroLiteral and
r.(SizeOfContainer).getContainerKind() = containerKind and
trueOrFalse = "false"
)
e instanceof GTExpr and
l instanceof IntegralZeroLiteral and
r.(SizeOfContainer).getContainerKind() = containerKind and
trueOrFalse = "false"
or
(
e instanceof GEExpr and
l.(SizeOfContainer).getContainerKind() = containerKind and
r instanceof IntegralZeroLiteral and
trueOrFalse = "true"
)
e instanceof GEExpr and
l.(SizeOfContainer).getContainerKind() = containerKind and
r instanceof IntegralZeroLiteral and
trueOrFalse = "true"
or
(
e instanceof LEExpr and
l instanceof IntegralZeroLiteral and
r.(SizeOfContainer).getContainerKind() = containerKind and
trueOrFalse = "true"
)
e instanceof LEExpr and
l instanceof IntegralZeroLiteral and
r.(SizeOfContainer).getContainerKind() = containerKind and
trueOrFalse = "true"
)
}

View File

@@ -83,10 +83,8 @@ private predicate closeableInit(Expr e, Expr parent) {
parent = arg
)
or
(
not exists(Expr arg | arg = cie.getAnArgument() | closeableType(arg.getType())) and
parent = cie
)
not exists(Expr arg | arg = cie.getAnArgument() | closeableType(arg.getType())) and
parent = cie
)
)
or
@@ -225,18 +223,16 @@ private predicate closeCalled(Variable v) {
exists(MethodAccess e |
v = getCloseableVariable(_) or v instanceof Parameter or v instanceof LocalVariableDecl
|
(
e.getMethod().getName().toLowerCase().matches("%close%") and
exists(VarAccess va | va = v.getAnAccess() |
e.getQualifier() = va or
e.getAnArgument() = va
)
e.getMethod().getName().toLowerCase().matches("%close%") and
exists(VarAccess va | va = v.getAnAccess() |
e.getQualifier() = va or
e.getAnArgument() = va
)
or
// The "close" call could happen indirectly inside a helper method of unknown name.
exists(int i | exprs(v.getAnAccess(), _, _, e, i) |
exists(Parameter p, int j | params(p, _, j, e.getMethod(), _) |
(closeCalled(p) and i = j)
closeCalled(p) and i = j
or
// The helper method could be iterating over a varargs parameter.
exists(EnhancedForStmt for | for.getExpr() = p.getAnAccess() |
@@ -276,9 +272,9 @@ private predicate immediatelyClosed(ClassInstanceExpr cie) {
* A unassigned or locally-assigned "closeable init" that does not escape and is not closed.
*/
private predicate badCloseableInitImpl(CloseableInitExpr cie) {
(unassignedCloseableInit(cie) and not immediatelyClosed(cie) and not escapingCloseableInit(cie))
unassignedCloseableInit(cie) and not immediatelyClosed(cie) and not escapingCloseableInit(cie)
or
(locallyInitializedCloseable(cie) and not closedResource(cie) and not escapingCloseableInit(cie))
locallyInitializedCloseable(cie) and not closedResource(cie) and not escapingCloseableInit(cie)
}
/**
@@ -297,7 +293,7 @@ predicate badCloseableInit(CloseableInitExpr cie) {
predicate noNeedToClose(CloseableInitExpr cie) {
locallyInitializedCloseable(cie) and
(
(cie instanceof ClassInstanceExpr and not exists(cie.(ClassInstanceExpr).getAnArgument()))
cie instanceof ClassInstanceExpr and not exists(cie.(ClassInstanceExpr).getAnArgument())
or
exists(RefType t | t = cie.getType() and t.fromSource() |
exists(Method close | close.getDeclaringType() = t and close.getName() = "close" |

View File

@@ -22,7 +22,7 @@ where
not exists(Constructor c |
c = nonserial.getSourceDeclaration().getAConstructor() and
c.hasNoParameters() and
not (c.isPrivate())
not c.isPrivate()
) and
serial.fromSource()
select serial,

View File

@@ -35,9 +35,9 @@ predicate sortedCollectionType(RefType t) {
string nameFor(Class c) {
nonSerializableComparator(c) and
(
(c instanceof AnonymousClass and result = "This comparator")
c instanceof AnonymousClass and result = "This comparator"
or
(not c instanceof AnonymousClass and result = c.getName())
not c instanceof AnonymousClass and result = c.getName()
)
}

View File

@@ -31,14 +31,10 @@ predicate collectionOrMapType(RefType t) { t instanceof CollectionType or t inst
predicate serializableType(RefType t) {
exists(RefType sup | sup = t.getASupertype*() | serializableOrExternalizable(sup))
or
(
// Collection interfaces are not serializable, but their implementations are
// likely to be.
collectionOrMapType(t) and
forall(RefType param | param = t.(ParameterizedType).getATypeArgument() |
serializableType(param)
)
)
// Collection interfaces are not serializable, but their implementations are
// likely to be.
collectionOrMapType(t) and
forall(RefType param | param = t.(ParameterizedType).getATypeArgument() | serializableType(param))
or
exists(BoundedType bt | bt = t | serializableType(bt.getUpperBoundType()))
}

View File

@@ -54,28 +54,26 @@ predicate exceptions(NestedClass inner) {
or
// The class `inner` is a local class or non-public member class and
// all its instance expressions are cast to non-serializable types.
(
(inner instanceof LocalClass or not inner.isPublic()) and
forall(ClassInstanceExpr cie, RefType target |
cie.getConstructedType() = inner and castTo(cie, target)
|
not isSerializable(target)
) and
// Exception 1: the expression is used as an argument to `writeObject()`.
not exists(Call writeCall, ClassInstanceExpr cie | cie.getConstructedType() = inner |
writeCall.getCallee().hasName("writeObject") and
writeCall.getAnArgument() = cie
) and
// Exception 2: the expression is thrown as an exception (exceptions should be serializable
// due to use cases such as remote procedure calls, logging, etc.)
not exists(ThrowStmt ts, ClassInstanceExpr cie |
cie.getConstructedType() = inner and
ts.getExpr() = cie
) and
// Exception 3: if the programmer added a `serialVersionUID`, we interpret that
// as an intent to make the class serializable.
not exists(Field f | f.getDeclaringType() = inner | f.hasName("serialVersionUID"))
)
(inner instanceof LocalClass or not inner.isPublic()) and
forall(ClassInstanceExpr cie, RefType target |
cie.getConstructedType() = inner and castTo(cie, target)
|
not isSerializable(target)
) and
// Exception 1: the expression is used as an argument to `writeObject()`.
not exists(Call writeCall, ClassInstanceExpr cie | cie.getConstructedType() = inner |
writeCall.getCallee().hasName("writeObject") and
writeCall.getAnArgument() = cie
) and
// Exception 2: the expression is thrown as an exception (exceptions should be serializable
// due to use cases such as remote procedure calls, logging, etc.)
not exists(ThrowStmt ts, ClassInstanceExpr cie |
cie.getConstructedType() = inner and
ts.getExpr() = cie
) and
// Exception 3: if the programmer added a `serialVersionUID`, we interpret that
// as an intent to make the class serializable.
not exists(Field f | f.getDeclaringType() = inner | f.hasName("serialVersionUID"))
}
from NestedClass inner, Class outer, string advice
@@ -86,7 +84,7 @@ where
not isSerializable(outer) and
not exceptions(inner) and
(
if (inner instanceof LocalClass)
if inner instanceof LocalClass
then advice = "Consider implementing readObject() and writeObject()."
else advice = "Consider making the class static or implementing readObject() and writeObject()."
)

View File

@@ -15,50 +15,44 @@ private predicate nonChaining(Method m) {
// The method has a body, and at least one of the return values is not suitable for chaining.
exists(ReturnStmt ret | ret.getEnclosingCallable() = m | nonChainingReturn(m, ret))
or
// The method has no body, and is not chaining because ...
not exists(m.getBody()) and
(
// The method has no body, and is not chaining because ...
not exists(m.getBody()) and
(
// ... it has the wrong return type, ...
not hasSubtype*(m.getReturnType(), m.getDeclaringType())
or
// ... it is defined on an immutable type, or ...
m.getDeclaringType() instanceof ImmutableType
or
// ... it has an override that is non-chaining.
exists(Method override | override.overrides(m) | nonChaining(override))
)
// ... it has the wrong return type, ...
not hasSubtype*(m.getReturnType(), m.getDeclaringType())
or
// ... it is defined on an immutable type, or ...
m.getDeclaringType() instanceof ImmutableType
or
// ... it has an override that is non-chaining.
exists(Method override | override.overrides(m) | nonChaining(override))
)
}
private predicate nonChainingReturn(Method m, ReturnStmt ret) {
// The wrong `this` is returned.
(
ret.getResult() instanceof ThisAccess and
ret.getResult().getType() != m.getDeclaringType()
)
ret.getResult() instanceof ThisAccess and
ret.getResult().getType() != m.getDeclaringType()
or
// A method call to the wrong method is returned.
(
ret.getResult() instanceof MethodAccess and
exists(MethodAccess delegateCall, Method delegate |
delegateCall = ret.getResult() and
delegate = delegateCall.getMethod()
|
delegate.getDeclaringType() != m.getDeclaringType()
or
delegate.isStatic()
or
not hasSubtype*(m.getReturnType(), delegate.getReturnType())
or
// A method on the wrong object is called.
not (
delegateCall.getQualifier().getProperExpr() instanceof ThisAccess or
not exists(delegateCall.getQualifier())
)
or
nonChaining(delegate)
ret.getResult() instanceof MethodAccess and
exists(MethodAccess delegateCall, Method delegate |
delegateCall = ret.getResult() and
delegate = delegateCall.getMethod()
|
delegate.getDeclaringType() != m.getDeclaringType()
or
delegate.isStatic()
or
not hasSubtype*(m.getReturnType(), delegate.getReturnType())
or
// A method on the wrong object is called.
not (
delegateCall.getQualifier().getProperExpr() instanceof ThisAccess or
not exists(delegateCall.getQualifier())
)
or
nonChaining(delegate)
)
or
// Something else is returned.

View File

@@ -43,18 +43,14 @@ Stmt emptyBody() { result = emptyBlock() or result = emptyStmt() }
predicate blockParent(Stmt empty, string msg) {
empty = emptyBody() and
(
(
empty.getParent() instanceof IfStmt and
msg = "The body of an if statement should not be empty."
)
empty.getParent() instanceof IfStmt and
msg = "The body of an if statement should not be empty."
or
(empty.getParent() instanceof LoopStmt and msg = "The body of a loop should not be empty.")
empty.getParent() instanceof LoopStmt and msg = "The body of a loop should not be empty."
or
(
empty.getParent() instanceof Block and
empty instanceof Block and
msg = "This block should not be empty."
)
empty.getParent() instanceof Block and
empty instanceof Block and
msg = "This block should not be empty."
)
}

View File

@@ -66,11 +66,9 @@ where
not rawTypeConversion(source, target) and
(
// No unchecked operations, so the cast would crash straight away.
(
not uncheckedCastType(target) and
message = "Impossible downcast: the cast from " + source.getName() + "[] to " +
target.getName() + "[] will always fail with a ClassCastException."
)
not uncheckedCastType(target) and
message = "Impossible downcast: the cast from " + source.getName() + "[] to " + target.getName()
+ "[] will always fail with a ClassCastException."
or
// For unchecked operations, the crash would not occur at the cast site,
// but only if/when the value is assigned to a variable of different array type.
@@ -78,16 +76,14 @@ where
// APIs. We keep two cases:
// - An array that is actually returned from the (non-private) method, or
// - an array that is assigned to a field returned from another (non-private) method.
(
uncheckedCastType(target) and
returnedFrom(ce, ce.getEnclosingCallable()) and
ce.getEnclosingCallable().getReturnType().(Array).getElementType() = target and
not ce.getEnclosingCallable().isPrivate() and
message = "Impossible downcast: this is returned by " + ce.getEnclosingCallable().getName() +
" as a value of type " + target.getName() + "[], but the array has type " +
source.getName() + "[]. Callers of " + ce.getEnclosingCallable().getName() +
" may fail with a ClassCastException."
)
uncheckedCastType(target) and
returnedFrom(ce, ce.getEnclosingCallable()) and
ce.getEnclosingCallable().getReturnType().(Array).getElementType() = target and
not ce.getEnclosingCallable().isPrivate() and
message = "Impossible downcast: this is returned by " + ce.getEnclosingCallable().getName() +
" as a value of type " + target.getName() + "[], but the array has type " + source.getName()
+ "[]. Callers of " + ce.getEnclosingCallable().getName() +
" may fail with a ClassCastException."
or
exists(Method m, Variable v |
uncheckedCastType(target) and

View File

@@ -18,7 +18,7 @@ import Chaining
predicate checkedMethodCall(MethodAccess ma) {
relevantMethodCall(ma, _) and
not (ma.getParent() instanceof ExprStmt)
not ma.getParent() instanceof ExprStmt
}
/**
@@ -35,7 +35,7 @@ predicate isMockingMethod(Method m) {
predicate isReceiverClauseMethod(Method m) {
m.getDeclaringType().getASupertype*().hasQualifiedName("org.jmock.syntax", "ReceiverClause") and
(m.hasName("of"))
m.hasName("of")
}
predicate isCardinalityClauseMethod(Method m) {
@@ -70,7 +70,7 @@ predicate isStubberMethod(Method m) {
*/
predicate isMustBeQualifierMockingMethod(Method m) {
m.getDeclaringType().getASupertype*().hasQualifiedName("org.mockito", "Mockito") and
(m.hasName("verify"))
m.hasName("verify")
}
predicate relevantMethodCall(MethodAccess ma, Method m) {

View File

@@ -81,5 +81,5 @@ where
not exists(MethodAccess ma | ma.getParent*() = cond) and
not exists(FieldRead fa | fa.getParent*() = cond) and
not exists(ArrayAccess aa | aa.getParent*() = cond)
select loop, "Loop might not terminate, as this $@ is constant within the loop.", cond,
"loop condition"
select cond, "$@ might not terminate, as this loop condition is constant within the loop.", loop,
"Loop"

View File

@@ -24,7 +24,7 @@ predicate realParent(Stmt inner, Stmt outer) {
predicate skipParent(Stmt s) {
exists(Stmt parent | parent = s.getParent() |
(s instanceof IfStmt and parent.(IfStmt).getElse() = s)
s instanceof IfStmt and parent.(IfStmt).getElse() = s
or
parent instanceof Block
)

View File

@@ -8,7 +8,7 @@
import java
private string prefix(Callable c) {
if (c instanceof Constructor and c.getDeclaringType() instanceof AnonymousClass)
if c instanceof Constructor and c.getDeclaringType() instanceof AnonymousClass
then result = "<anonymous constructor>"
else result = ""
}

View File

@@ -19,20 +19,18 @@ class RangeCallable extends Callable {
exists(int elSuper, int ecSuper | super.hasLocationInfo(path, sl, sc, elSuper, ecSuper) |
this.getBody().hasLocationInfo(path, _, _, el, ec)
or
not exists(this.getBody()) and
(
not exists(this.getBody()) and
(
lastParameter().hasLocationInfo(path, _, _, el, ec)
or
(not exists(this.getAParameter()) and el = elSuper and ec = ecSuper)
)
lastParameter().hasLocationInfo(path, _, _, el, ec)
or
not exists(this.getAParameter()) and el = elSuper and ec = ecSuper
)
)
}
private Parameter lastParameter() {
result = getAParameter() and
not (getAParameter().getPosition() > result.getPosition())
not getAParameter().getPosition() > result.getPosition()
}
}
@@ -45,7 +43,7 @@ class RangeRefType extends RefType {
exists(int elSuper, int ecSuper | super.hasLocationInfo(path, sl, sc, elSuper, ecSuper) |
lastMember().hasLocationInfo(path, _, _, el, ec)
or
(not exists(this.getAMember()) and el = elSuper and ec = ecSuper)
not exists(this.getAMember()) and el = elSuper and ec = ecSuper
)
}

View File

@@ -22,7 +22,7 @@ int complexCallableLines(MetricCallable c, RefType owner) {
from MetricRefType t, int ccLoc, int loc
where
t.fromSource() and
not (t instanceof GeneratedClass) and
not t instanceof GeneratedClass and
ccLoc = sum(Callable c, int cLoc | cLoc = complexCallableLines(c, t) | cLoc) and
loc = t.getNumberOfLinesOfCode() and
loc != 0

View File

@@ -38,10 +38,8 @@ predicate useAndDef(Assignment a, Variable v) {
(
a instanceof AssignAddExpr
or
(
exists(VarAccess use | use.getVariable() = v | use.getParent*() = a.getSource()) and
a.getSource() instanceof AddExpr
)
exists(VarAccess use | use.getVariable() = v | use.getParent*() = a.getSource()) and
a.getSource() instanceof AddExpr
)
}

View File

@@ -20,7 +20,7 @@ import java
predicate inherits(Class c, Field f) {
f = c.getAField()
or
(not f.isPrivate() and c.getASupertype+().getAField() = f)
not f.isPrivate() and c.getASupertype+().getAField() = f
}
/**
@@ -37,10 +37,10 @@ RefType enclosingInstanceAccess(Expr expr) {
exists(RefType enclosing | enclosing = expr.getEnclosingCallable().getDeclaringType() |
// A direct qualified `this` access that doesn't refer to the containing
// class must refer to an enclosing instance instead.
(result = expr.(ThisAccess).getType() and result != enclosing)
result = expr.(ThisAccess).getType() and result != enclosing
or
// A qualified `super` access qualified with a type that isn't the enclosing type.
(result = expr.(SuperAccess).getQualifier().(TypeAccess).getType() and result != enclosing)
result = expr.(SuperAccess).getQualifier().(TypeAccess).getType() and result != enclosing
or
// An unqualified `new` expression constructing a
// non-static type that needs an enclosing instance.
@@ -94,7 +94,7 @@ predicate potentiallyStatic(InnerClass c) {
InnerClass other // If nested and non-static, ...
|
// ... all supertypes (which are from source), ...
(other = c.getASourceSupertype() and other.fromSource())
other = c.getASourceSupertype() and other.fromSource()
or
// ... and the enclosing type, ...
other = c.getEnclosingType()

View File

@@ -10,6 +10,7 @@
*/
import java
import semmle.code.java.dataflow.TypeFlow
import semmle.code.java.security.Encryption
class URLConnection extends RefType {
@@ -27,11 +28,15 @@ from MethodAccess m, Class c, string type
where
m.getQualifier().getType() = c and
(
(c instanceof URLConnection and type = "connection")
c instanceof URLConnection and type = "connection"
or
(c instanceof Socket and type = "socket")
c instanceof Socket and type = "socket"
) and
not c instanceof SSLClass and
not exists(RefType t |
exprTypeFlow(m.getQualifier(), t, _) and
t instanceof SSLClass
) and
(
m.getMethod().getName() = "getInputStream" or
m.getMethod().getName() = "getOutputStream"

View File

@@ -172,20 +172,18 @@ class SafeDocumentBuilderFactory extends VarAccess {
config.enables(singleSafeConfig())
)
or
(
//These two need to be set together to work
exists(DocumentBuilderFactoryConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(DocumentBuilderFactoryConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
)
//These two need to be set together to work
exists(DocumentBuilderFactoryConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(DocumentBuilderFactoryConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
)
)
}
@@ -682,25 +680,23 @@ class SafeXMLReaderFlowSink extends Expr {
class ExplicitlySafeXMLReader extends VarAccess {
ExplicitlySafeXMLReader() {
exists(Variable v | v = this.getVariable() |
(
exists(XMLReaderConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(XMLReaderConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
) and
exists(XMLReaderConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://apache.org/xml/features/nonvalidating/load-external-dtd"
))
)
exists(XMLReaderConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(XMLReaderConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
) and
exists(XMLReaderConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://apache.org/xml/features/nonvalidating/load-external-dtd"
))
)
or
exists(XMLReaderConfig config | config.getQualifier() = v.getAnAccess() |

View File

@@ -104,7 +104,7 @@ private int anyCount(JavadocFirst first) {
class CommentedOutCode extends JavadocFirst {
CommentedOutCode() {
anyCount(this) > 0 and
(codeCount(this).(float)) / (anyCount(this).(float)) > 0.5 and
codeCount(this).(float) / anyCount(this).(float) > 0.5 and
not this instanceof JSNIComment and
not this instanceof OCNIComment
}

View File

@@ -21,7 +21,7 @@ predicate nonEmptyArrayLiteralOrNull(Expr e) {
// Array creation with dimensions (but without initializers).
// Empty if the first dimension is 0.
exists(Expr dim | dim = arr.getDimension(0) |
not (dim.(CompileTimeConstantExpr).getIntValue() = 0)
not dim.(CompileTimeConstantExpr).getIntValue() = 0
)
)
or

View File

@@ -352,7 +352,7 @@ private predicate candidateConstantForLiteral(
}
private RefType inheritsProtected(Field f) {
(f.isProtected() and result.getASupertype() = f.getDeclaringType())
f.isProtected() and result.getASupertype() = f.getDeclaringType()
or
exists(RefType mid | mid = inheritsProtected(f) and result.getASupertype() = mid)
}
@@ -361,40 +361,32 @@ private predicate constantForLiteral(
Field field, string value, RefType fromType, Literal magicLiteral, string context
) {
//public fields in public classes
(
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
field.getDeclaringType().isPublic() and
field.isPublic() and
relevantType(fromType, value, _)
)
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
field.getDeclaringType().isPublic() and
field.isPublic() and
relevantType(fromType, value, _)
or
//in same class
(
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
fromType = field.getDeclaringType() and
relevantType(fromType, value, _)
)
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
fromType = field.getDeclaringType() and
relevantType(fromType, value, _)
or
//in subclass and not private
(
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
field.isProtected() and
fromType = inheritsProtected(field) and
relevantType(fromType, value, _)
)
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
field.isProtected() and
fromType = inheritsProtected(field) and
relevantType(fromType, value, _)
or
//not private and in same package
(
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
field.isPackageProtected() and
exists(Package p |
exists(CompilationUnit cu | cu = field.getCompilationUnit() and cu.getPackage() = p) and
relevantType(fromType, value, p)
)
candidateConstantForLiteral(field, fromType, magicLiteral, context) and
relevantField(field, value) and
field.isPackageProtected() and
exists(Package p |
exists(CompilationUnit cu | cu = field.getCompilationUnit() and cu.getPackage() = p) and
relevantType(fromType, value, p)
)
}

View File

@@ -32,7 +32,7 @@ Variable flowTarget(Expr arg) {
*/
predicate unboxed(BoxedExpr e) {
exists(BinaryExpr bin | e = bin.getAnOperand() |
if (bin instanceof EqualityTest or bin instanceof ComparisonExpr)
if bin instanceof EqualityTest or bin instanceof ComparisonExpr
then bin.getAnOperand() instanceof PrimitiveExpr
else bin instanceof PrimitiveExpr
)

View File

@@ -28,7 +28,7 @@ RefType normalised(Type type) {
or
type.(BoundedType).getUpperBoundType() = result
or
(not type instanceof RawType and not type instanceof ParameterizedType and type = result)
not type instanceof RawType and not type instanceof ParameterizedType and type = result
}
predicate equivalent(Array declared, Array used) {

View File

@@ -33,7 +33,7 @@ class LocationOverridingMethodAccess extends MethodAccess {
super.hasLocationInfo(path, slSuper, scSuper, elSuper, ecSuper)
|
(
if (exists(getTypeArgument(_)))
if exists(getTypeArgument(_))
then
exists(Location locTypeArg |
locTypeArg = getTypeArgument(count(getTypeArgument(_)) - 1).getLocation()
@@ -56,7 +56,7 @@ class LocationOverridingMethodAccess extends MethodAccess {
)
) and
(
if (getNumArgument() > 0)
if getNumArgument() > 0
then
// Note: this needs to be the original (full) location of the first argument, not the modified one.
exists(Location locArg | locArg = getArgument(0).getLocation() |
@@ -95,7 +95,7 @@ class LocationOverridingTypeAccess extends TypeAccess {
)
) and
(
if (exists(getTypeArgument(_)))
if exists(getTypeArgument(_))
then
// Note: this needs to be the original (full) location of the first type argument, not the modified one.
exists(Location locArg | locArg = getTypeArgument(0).getLocation() |
@@ -119,7 +119,7 @@ class LocationOverridingFieldAccess extends FieldAccess {
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
super.hasLocationInfo(path, _, _, el, ec) and
sl = el and
sc = ec - (getField().getName().length()) + 1
sc = ec - getField().getName().length() + 1
}
}
@@ -135,7 +135,7 @@ class LocationOverridingImportType extends ImportType {
el = elSuper and
ec = ecSuper - 1 and
sl = el and
sc = ecSuper - (getImportedType().getName().length())
sc = ecSuper - getImportedType().getName().length()
)
}
}
@@ -152,7 +152,7 @@ class LocationOverridingImportStaticTypeMember extends ImportStaticTypeMember {
el = elSuper and
ec = ecSuper - 1 and
sl = el and
sc = ecSuper - (getName().length())
sc = ecSuper - getName().length()
)
}
}

View File

@@ -120,7 +120,7 @@ class CloverClass extends CloverMetricsContainer {
this.getName() = "class"
}
CloverPackage getPackage() { result = (getParent().(CloverFile)).getParent() }
CloverPackage getPackage() { result = getParent().(CloverFile).getParent() }
RefType getRealClass() {
result

View File

@@ -108,7 +108,7 @@ predicate similarLines(File f, int line) {
private predicate similarLinesPerEquivalenceClass(int equivClass, int lines, File f) {
lines = strictsum(SimilarBlock b, int toSum |
(b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and
(toSum = b.sourceLines())
toSum = b.sourceLines()
|
toSum
)
@@ -143,7 +143,7 @@ predicate duplicateLines(File f, int line) {
private predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, File f) {
lines = strictsum(DuplicateBlock b, int toSum |
(b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and
(toSum = b.sourceLines())
toSum = b.sourceLines()
|
toSum
)
@@ -227,25 +227,21 @@ predicate mostlyDuplicateClass(Class c, Class other, string message) {
not c instanceof AnonymousClass and
not other instanceof AnonymousClass and
(
(
total != numDup and
exists(string s1, string s2, string s3, string name |
s1 = " out of " and
s2 = " methods in " and
s3 = " are duplicated in $@." and
name = c.getName()
|
message = numDup + s1 + total + s2 + name + s3
)
total != numDup and
exists(string s1, string s2, string s3, string name |
s1 = " out of " and
s2 = " methods in " and
s3 = " are duplicated in $@." and
name = c.getName()
|
message = numDup + s1 + total + s2 + name + s3
)
or
(
total = numDup and
exists(string s1, string s2, string name |
s1 = "All methods in " and s2 = " are identical in $@." and name = c.getName()
|
message = s1 + name + s2
)
total = numDup and
exists(string s1, string s2, string name |
s1 = "All methods in " and s2 = " are identical in $@." and name = c.getName()
|
message = s1 + name + s2
)
)
)

View File

@@ -18,9 +18,9 @@ class ExternalData extends @externalDataElement {
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
private string buildTupleString(int start) {
(start = getNumFields() - 1 and result = getField(start))
start = getNumFields() - 1 and result = getField(start)
or
(start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1))
start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1)
}
}

View File

@@ -37,7 +37,7 @@ class SuppressionComment extends Javadoc {
result = "\\Q" + substring.replaceAll("\\E", "\\E\\\\E\\Q") + "\\E"
)
or
(result = ".*" and getASuppressionDirective() = "NOSEMMLE")
result = ".*" and getASuppressionDirective() = "NOSEMMLE"
}
predicate suppresses(DefectResult res) {

View File

@@ -109,7 +109,7 @@ class Location extends @location {
exists(@sourceline s | hasLocation(s, this) |
numlines(s, result, _, _)
or
(not numlines(s, _, _, _) and result = 0)
not numlines(s, _, _, _) and result = 0
)
}
@@ -118,7 +118,7 @@ class Location extends @location {
exists(@sourceline s | hasLocation(s, this) |
numlines(s, _, result, _)
or
(not numlines(s, _, _, _) and result = 0)
not numlines(s, _, _, _) and result = 0
)
}
@@ -127,7 +127,7 @@ class Location extends @location {
exists(@sourceline s | hasLocation(s, this) |
numlines(s, _, _, result)
or
(not numlines(s, _, _, _) and result = 0)
not numlines(s, _, _, _) and result = 0
)
}
@@ -169,5 +169,5 @@ cached
private predicate fixedHasLocation(Top l, Location loc, File f) {
hasSourceLocation(l, loc, f)
or
(hasLocation(l, loc) and not hasSourceLocation(l, _, _) and locations_default(loc, f, _, _, _, _))
hasLocation(l, loc) and not hasSourceLocation(l, _, _) and locations_default(loc, f, _, _, _, _)
}

View File

@@ -112,7 +112,7 @@ class Annotatable extends Element {
*/
predicate suppressesWarningsAbout(string category) {
exists(string withQuotes |
withQuotes = (getAnAnnotation().(SuppressWarningsAnnotation)).getASuppressedWarning()
withQuotes = getAnAnnotation().(SuppressWarningsAnnotation).getASuppressedWarning()
|
category = withQuotes.substring(1, withQuotes.length() - 1)
)

View File

@@ -51,15 +51,11 @@ private predicate hasChildElement(Element parent, Element e) {
or
enclInReftype(e, parent)
or
(
not (enclInReftype(e, _)) and
e.(Class).getCompilationUnit() = parent
)
not enclInReftype(e, _) and
e.(Class).getCompilationUnit() = parent
or
(
not (enclInReftype(e, _)) and
e.(Interface).getCompilationUnit() = parent
)
not enclInReftype(e, _) and
e.(Interface).getCompilationUnit() = parent
or
methods(e, _, _, _, parent, _)
or

View File

@@ -139,10 +139,8 @@ class CompileTimeConstantExpr extends Expr {
// the bitwise and logical operators `&`, `^`, and `|`,
// the conditional-and operator `&&` and the conditional-or operator `||`.
// These are precisely the operators represented by `BinaryExpr`.
(
this.(BinaryExpr).getLeftOperand().isCompileTimeConstant() and
this.(BinaryExpr).getRightOperand().isCompileTimeConstant()
)
this.(BinaryExpr).getLeftOperand().isCompileTimeConstant() and
this.(BinaryExpr).getRightOperand().isCompileTimeConstant()
or
// The ternary conditional operator ` ? : `.
exists(ConditionalExpr e | this = e |
@@ -252,17 +250,13 @@ class CompileTimeConstantExpr extends Expr {
if left != right then result = true else result = false
)
or
(
(b instanceof AndBitwiseExpr or b instanceof AndLogicalExpr) and
result = left.booleanAnd(right)
)
(b instanceof AndBitwiseExpr or b instanceof AndLogicalExpr) and
result = left.booleanAnd(right)
or
(
(b instanceof OrBitwiseExpr or b instanceof OrLogicalExpr) and
result = left.booleanOr(right)
)
(b instanceof OrBitwiseExpr or b instanceof OrLogicalExpr) and
result = left.booleanOr(right)
or
(b instanceof XorBitwiseExpr and result = left.booleanXor(right))
b instanceof XorBitwiseExpr and result = left.booleanXor(right)
)
or
// Handle binary expressions that have `String` operands and a boolean result.
@@ -342,7 +336,7 @@ class CompileTimeConstantExpr extends Expr {
or
result = this.(PlusExpr).getExpr().(CompileTimeConstantExpr).getIntValue()
or
result = -(this.(MinusExpr).getExpr().(CompileTimeConstantExpr).getIntValue())
result = -this.(MinusExpr).getExpr().(CompileTimeConstantExpr).getIntValue()
or
result = this.(BitNotExpr).getExpr().(CompileTimeConstantExpr).getIntValue().bitNot()
or
@@ -1189,12 +1183,7 @@ abstract class InstanceAccess extends Expr {
class ThisAccess extends InstanceAccess, @thisaccess {
/** Gets a printable representation of this expression. */
override string toString() {
if exists(this.getQualifier())
then (
result = this.getQualifier() + ".this"
) else (
result = "this"
)
if exists(this.getQualifier()) then result = this.getQualifier() + ".this" else result = "this"
}
}
@@ -1208,11 +1197,8 @@ class SuperAccess extends InstanceAccess, @superaccess {
/** Gets a printable representation of this expression. */
override string toString() {
if exists(this.getQualifier())
then (
result = this.getQualifier() + ".super"
) else (
result = "super"
)
then result = this.getQualifier() + ".super"
else result = "super"
}
}
@@ -1257,7 +1243,7 @@ class VarAccess extends Expr, @varaccess {
override string toString() {
result = this.getQualifier().toString() + "." + this.getVariable().getName()
or
(not this.hasQualifier() and result = this.getVariable().getName())
not this.hasQualifier() and result = this.getVariable().getName()
}
/**
@@ -1391,7 +1377,7 @@ class TypeAccess extends Expr, Annotatable, @typeaccess {
override string toString() {
result = this.getQualifier().toString() + "." + this.getType().toString()
or
(not this.hasQualifier() and result = this.getType().toString())
not this.hasQualifier() and result = this.getType().toString()
}
}

View File

@@ -56,11 +56,9 @@ class JMXRegistrationCall extends MethodAccess {
*/
class JMXRegistrationMethod extends Method {
JMXRegistrationMethod() {
(
// A direct registration with the `MBeanServer`.
getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and
getName() = "registerMBean"
)
// A direct registration with the `MBeanServer`.
getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and
getName() = "registerMBean"
or
// The `MBeanServer` is often wrapped by an application specific management class, so identify
// methods that wrap a call to another `JMXRegistrationMethod`.
@@ -75,12 +73,10 @@ class JMXRegistrationMethod extends Method {
* Gets the position of the parameter through which the "object" to be registered is passed.
*/
int getObjectPosition() {
(
// Passed as the first argument to `registerMBean`.
getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and
getName() = "registerMBean" and
result = 0
)
// Passed as the first argument to `registerMBean`.
getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and
getName() = "registerMBean" and
result = 0
or
// Identify the position in this method where the object parameter should be passed.
exists(JMXRegistrationCall c |

View File

@@ -74,7 +74,7 @@ class Callable extends StmtParent, Member, @callable {
}
private string descriptorUpTo(int n) {
(n = 0 and result = "")
n = 0 and result = ""
or
exists(Parameter p | p = this.getParameter(n - 1) |
result = descriptorUpTo(n - 1) + p.getType().getTypeDescriptor()

View File

@@ -129,10 +129,8 @@ private Type parameterForSubTypes(ParameterizedType type) {
// Must not be a catch-all.
not catchallType(arg)
|
(
// Simple case - this type is not a bounded type, so must represent exactly the `arg` class.
not arg instanceof BoundedType and result = arg
)
// Simple case - this type is not a bounded type, so must represent exactly the `arg` class.
not arg instanceof BoundedType and result = arg
or
exists(RefType upperBound |
// Upper bound case
@@ -173,7 +171,7 @@ Type inferClassParameterType(Expr expr) {
// We've been able to identify where this `Class` instance was created, and identified the
// particular class that was loaded.
result = pointsToReflectiveClassIdentifier(expr).getReflectivelyIdentifiedClass()
else (
else
// If we haven't been able to find where the value for this expression was defined, then we
// resort to the type `T` in `Class<T>`.
//
@@ -183,7 +181,6 @@ Type inferClassParameterType(Expr expr) {
// A "catch-all" type is something like `? extends Object` or `? extends Serialization`, which
// would return too many sub-types.
result = parameterForSubTypes(expr.getType())
)
)
}
@@ -290,12 +287,10 @@ class NewInstance extends MethodAccess {
exists(CastExpr cast | cast.getExpr() = this or cast.getExpr().(ParExpr).getExpr() = this |
result = cast.getType()
or
(
// If we cast the result of this method, then this is either the type specified, or a
// sub-type of that type. Make sure we exclude overly generic types such as `Object`.
not overlyGenericType(cast.getType()) and
hasSubtype*(cast.getType(), result)
)
// If we cast the result of this method, then this is either the type specified, or a
// sub-type of that type. Make sure we exclude overly generic types such as `Object`.
not overlyGenericType(cast.getType()) and
hasSubtype*(cast.getType(), result)
)
}
}

View File

@@ -118,7 +118,7 @@ class IfStmt extends ConditionalStmt, @ifstmt {
override string pp() {
result = "if (...) " + this.getThen().pp() + " else " + this.getElse().pp()
or
(not exists(this.getElse()) and result = "if (...) " + this.getThen().pp())
not exists(this.getElse()) and result = "if (...) " + this.getThen().pp()
}
/** This statement's Halstead ID (used to compute Halstead metrics). */
@@ -495,7 +495,7 @@ class ThrowStmt extends Stmt, @throwstmt {
private CatchClause catchClauseForThis(TryStmt try) {
result = try.getACatchClause() and
result.getEnclosingCallable() = this.getEnclosingCallable() and
(getExpr().getType().(RefType)).hasSupertype*(result.getVariable().getType().(RefType)) and
getExpr().getType().(RefType).hasSupertype*(result.getVariable().getType().(RefType)) and
not this.getParent+() = result
}
}
@@ -538,7 +538,7 @@ class JumpStmt extends Stmt {
Stmt getTarget() {
result = getLabelTarget()
or
(not exists(getLabelTarget()) and result = getEnclosingTarget())
not exists(getLabelTarget()) and result = getEnclosingTarget()
}
}

View File

@@ -20,21 +20,21 @@ import JDK
cached
predicate hasSubtype(RefType t, Type sub) {
// Direct subtype.
(extendsReftype(sub, t) and t != sub)
extendsReftype(sub, t) and t != sub
or
implInterface(sub, t)
or
// A parameterized type `T<A>` is a subtype of the corresponding raw type `T<>`.
(parSubtypeRaw(t, sub) and t != sub)
parSubtypeRaw(t, sub) and t != sub
or
// Array subtyping is covariant.
(arraySubtype(t, sub) and t != sub)
arraySubtype(t, sub) and t != sub
or
// Type parameter containment for parameterized types.
(parContainmentSubtype(t, sub) and t != sub)
parContainmentSubtype(t, sub) and t != sub
or
// Type variables are subtypes of their upper bounds.
(typeVarSubtypeBound(t, sub) and t != sub)
typeVarSubtypeBound(t, sub) and t != sub
}
private predicate typeVarSubtypeBound(RefType t, TypeVariable tv) {
@@ -825,21 +825,21 @@ class PrimitiveType extends Type, @primitive {
* Gets the JVM descriptor for this type, as used in bytecode.
*/
override string getTypeDescriptor() {
(this.hasName("float") and result = "F")
this.hasName("float") and result = "F"
or
(this.hasName("double") and result = "D")
this.hasName("double") and result = "D"
or
(this.hasName("int") and result = "I")
this.hasName("int") and result = "I"
or
(this.hasName("boolean") and result = "Z")
this.hasName("boolean") and result = "Z"
or
(this.hasName("short") and result = "S")
this.hasName("short") and result = "S"
or
(this.hasName("byte") and result = "B")
this.hasName("byte") and result = "B"
or
(this.hasName("char") and result = "C")
this.hasName("char") and result = "C"
or
(this.hasName("long") and result = "J")
this.hasName("long") and result = "J"
}
/**
@@ -896,21 +896,21 @@ class BoxedType extends RefType {
/** Gets the primitive type corresponding to this boxed type. */
PrimitiveType getPrimitiveType() {
(this.hasName("Float") and result.hasName("float"))
this.hasName("Float") and result.hasName("float")
or
(this.hasName("Double") and result.hasName("double"))
this.hasName("Double") and result.hasName("double")
or
(this.hasName("Integer") and result.hasName("int"))
this.hasName("Integer") and result.hasName("int")
or
(this.hasName("Boolean") and result.hasName("boolean"))
this.hasName("Boolean") and result.hasName("boolean")
or
(this.hasName("Short") and result.hasName("short"))
this.hasName("Short") and result.hasName("short")
or
(this.hasName("Byte") and result.hasName("byte"))
this.hasName("Byte") and result.hasName("byte")
or
(this.hasName("Character") and result.hasName("char"))
this.hasName("Character") and result.hasName("char")
or
(this.hasName("Long") and result.hasName("long"))
this.hasName("Long") and result.hasName("long")
}
}

View File

@@ -7,46 +7,46 @@ class OrdPrimitiveType extends PrimitiveType {
predicate widerThanOrEqualTo(OrdPrimitiveType that) { getWidthRank() >= that.getWidthRank() }
OrdPrimitiveType maxType(OrdPrimitiveType that) {
(this.widerThan(that) and result = this)
this.widerThan(that) and result = this
or
(not this.widerThan(that) and result = that)
not this.widerThan(that) and result = that
}
int getWidthRank() {
(this.getName() = "byte" and result = 1)
this.getName() = "byte" and result = 1
or
(this.getName() = "short" and result = 2)
this.getName() = "short" and result = 2
or
(this.getName() = "int" and result = 3)
this.getName() = "int" and result = 3
or
(this.getName() = "long" and result = 4)
this.getName() = "long" and result = 4
or
(this.getName() = "float" and result = 5)
this.getName() = "float" and result = 5
or
(this.getName() = "double" and result = 6)
this.getName() = "double" and result = 6
}
float getMaxValue() {
(this.getName() = "byte" and result = 127.0)
this.getName() = "byte" and result = 127.0
or
(this.getName() = "short" and result = 32767.0)
this.getName() = "short" and result = 32767.0
or
(this.getName() = "int" and result = 2147483647.0)
this.getName() = "int" and result = 2147483647.0
or
// Long.MAX_VALUE is 9223372036854775807 but floating point only has 53 bits of precision.
(this.getName() = "long" and result = 9223372036854776000.0)
this.getName() = "long" and result = 9223372036854776000.0
// don't try for floats and doubles
}
float getMinValue() {
(this.getName() = "byte" and result = -128.0)
this.getName() = "byte" and result = -128.0
or
(this.getName() = "short" and result = -32768.0)
this.getName() = "short" and result = -32768.0
or
(this.getName() = "int" and result = -2147483648.0)
this.getName() = "int" and result = -2147483648.0
or
// Long.MIN_VALUE is -9223372036854775808 but floating point only has 53 bits of precision.
(this.getName() = "long" and result = -9223372036854776000.0)
this.getName() = "long" and result = -9223372036854776000.0
// don't try for floats and doubles
}
}
@@ -59,9 +59,9 @@ class NumType extends Type {
/** Gets the width-ordered primitive type corresponding to this type. */
OrdPrimitiveType getOrdPrimitiveType() {
(this instanceof PrimitiveType and result = this)
this instanceof PrimitiveType and result = this
or
(this instanceof BoxedType and result = this.(BoxedType).getPrimitiveType())
this instanceof BoxedType and result = this.(BoxedType).getPrimitiveType()
}
predicate widerThan(NumType that) {

View File

@@ -25,10 +25,8 @@ class ConstantField extends Field {
fa.getEnclosingCallable() instanceof InstanceInitializer
or
// It can be defined in the constructor if there is only one constructor.
(
fa.getEnclosingCallable() instanceof Constructor and
count(getDeclaringType().getAConstructor()) = 1
)
fa.getEnclosingCallable() instanceof Constructor and
count(getDeclaringType().getAConstructor()) = 1
)
)
}
@@ -93,10 +91,8 @@ class ConstantExpr extends Expr {
exists(this.(FieldRead).getField().(ConstantField).getConstantValue())
or
// A binary expression where both sides are constant
(
this.(BinaryExpr).getLeftOperand() instanceof ConstantExpr and
this.(BinaryExpr).getRightOperand() instanceof ConstantExpr
)
this.(BinaryExpr).getLeftOperand() instanceof ConstantExpr and
this.(BinaryExpr).getRightOperand() instanceof ConstantExpr
or
this.(ParExpr).getExpr() instanceof ConstantExpr
)
@@ -179,7 +175,7 @@ class ConstSwitchStmt extends SwitchStmt {
SwitchCase getMatchingCase() {
// Must be a value we can deduce
exists(getExpr().(ConstantExpr).getIntValue()) and
if (exists(getMatchingConstCase()))
if exists(getMatchingConstCase())
then result = getMatchingConstCase()
else result = getDefaultCase()
}
@@ -216,14 +212,12 @@ class UnreachableBasicBlock extends BasicBlock {
or
// This block is not reachable in the CFG, and is not a callable, a body of a callable, an
// expression in an annotation, an expression in an assert statement, or a catch clause.
(
forall(BasicBlock bb | bb = getABBPredecessor() | bb instanceof UnreachableBasicBlock) and
not exists(Callable c | c.getBody() = this) and
not this instanceof Callable and
not exists(Annotation a | a.getAChildExpr*() = this) and
not exists(AssertStmt a | a = this.(Expr).getEnclosingStmt()) and
not this instanceof CatchClause
)
forall(BasicBlock bb | bb = getABBPredecessor() | bb instanceof UnreachableBasicBlock) and
not exists(Callable c | c.getBody() = this) and
not this instanceof Callable and
not exists(Annotation a | a.getAChildExpr*() = this) and
not exists(AssertStmt a | a = this.(Expr).getEnclosingStmt()) and
not this instanceof CatchClause
or
// Switch statements with a constant comparison expression may have unreachable cases.
exists(ConstSwitchStmt constSwitchStmt, BasicBlock failingCaseBlock |

View File

@@ -94,6 +94,34 @@ Expr clearlyNotNullExpr() { result = clearlyNotNullExpr(_) }
/** Holds if `v` is an SSA variable that is provably not `null`. */
predicate clearlyNotNull(SsaVariable v) { clearlyNotNull(v, _) }
/**
* Holds if the evaluation of a call to `m` resulting in the value `branch`
* implies that the argument to the call is guaranteed to be null if `isnull`
* is true, and non-null if `isnull` is false.
*/
predicate nullCheckMethod(Method m, boolean branch, boolean isnull) {
exists(boolean polarity |
m.getDeclaringType().hasQualifiedName("java.util", "Objects") and
(
m.hasName("isNull") and polarity = true
or
m.hasName("nonNull") and polarity = false
) and
(
branch = true and isnull = polarity
or
branch = false and isnull = polarity.booleanNot()
)
)
or
m instanceof EqualsMethod and branch = true and isnull = false
or
m.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "StringUtils") and
m.hasName("isBlank") and
branch = false and
isnull = false
}
/**
* Gets an expression that directly tests whether a given expression, `e`, is null or not.
*
@@ -114,29 +142,10 @@ Expr basicNullGuard(Expr e, boolean branch, boolean isnull) {
or
result.(InstanceOfExpr).getExpr() = e and branch = true and isnull = false
or
exists(MethodAccess call, Method m, boolean polarity |
call = result and
call.getAnArgument() = e and
call.getMethod() = m and
m.getDeclaringType().hasQualifiedName("java.util", "Objects") and
(
m.hasName("isNull") and polarity = true
or
m.hasName("nonNull") and polarity = false
) and
(
branch = true and isnull = polarity
or
branch = false and isnull = polarity.booleanNot()
)
)
or
exists(MethodAccess call |
call = result and
call.getAnArgument() = e and
call.getMethod() instanceof EqualsMethod and
branch = true and
isnull = false
nullCheckMethod(call.getMethod(), branch, isnull)
)
or
exists(EqualityTest eqtest |

View File

@@ -336,11 +336,11 @@ private predicate nullVarStep(
not exists(boolean branch | nullGuard(midssa, branch, false).hasBranchEdge(mid, bb, branch)) and
not (leavingFinally(mid, bb, true) and midstoredcompletion = true) and
if bb.getFirstNode() = any(TryStmt try | | try.getFinally())
then (
then
if bb.getFirstNode() = mid.getLastNode().getANormalSuccessor()
then storedcompletion = false
else storedcompletion = true
) else
else
if leavingFinally(mid, bb, _)
then storedcompletion = false
else storedcompletion = midstoredcompletion

View File

@@ -232,11 +232,11 @@ private Guard boundFlowCond(SsaVariable v, Expr e, int delta, boolean upper, boo
) and
(
if v.getSourceVariable().getType() instanceof IntegralType
then (
then
upper = true and strengthen = -1
or
upper = false and strengthen = 1
) else strengthen = 0
else strengthen = 0
) and
(
exists(int k | modulusComparison(comp, testIsTrue, k) and d2 = strengthen * k)
@@ -402,17 +402,14 @@ private predicate boundFlowStep(Expr e2, Expr e1, int delta, boolean upper) {
not x instanceof ConstantIntegerExpr and
not e1 instanceof ConstantIntegerExpr and
if strictlyPositive(x)
then (
upper = false and delta = 1
) else
then upper = false and delta = 1
else
if positive(x)
then (
upper = false and delta = 0
) else
then upper = false and delta = 0
else
if strictlyNegative(x)
then (
upper = true and delta = -1
) else if negative(x) then (upper = true and delta = 0) else none()
then upper = true and delta = -1
else if negative(x) then upper = true and delta = 0 else none()
)
or
exists(Expr x |
@@ -431,17 +428,14 @@ private predicate boundFlowStep(Expr e2, Expr e1, int delta, boolean upper) {
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
not x instanceof ConstantIntegerExpr and
if strictlyPositive(x)
then (
upper = true and delta = -1
) else
then upper = true and delta = -1
else
if positive(x)
then (
upper = true and delta = 0
) else
then upper = true and delta = 0
else
if strictlyNegative(x)
then (
upper = false and delta = 1
) else if negative(x) then (upper = false and delta = 0) else none()
then upper = false and delta = 1
else if negative(x) then upper = false and delta = 0 else none()
)
or
e2.(RemExpr).getRightOperand() = e1 and positive(e1) and delta = -1 and upper = true

View File

@@ -18,35 +18,29 @@ predicate isLive(Callable c) {
* would imply the liveness of `c`.
*/
Callable possibleLivenessCause(Callable c, string reason) {
(
c.(Method).overridesOrInstantiates(result.(Method)) and
reason = "is overridden or instantiated by"
)
c.(Method).overridesOrInstantiates(result.(Method)) and
reason = "is overridden or instantiated by"
or
(result.calls(c) and reason = "calls")
result.calls(c) and reason = "calls"
or
(result.callsConstructor(c.(Constructor)) and reason = "calls constructor")
result.callsConstructor(c.(Constructor)) and reason = "calls constructor"
or
exists(ClassInstanceExpr e | e.getEnclosingCallable() = result |
e.getConstructor() = c and reason = "constructs"
)
or
(c = result.getSourceDeclaration() and c != result and reason = "instantiates")
c = result.getSourceDeclaration() and c != result and reason = "instantiates"
or
(
c.hasName("<clinit>") and
reason = "class initialization" and
exists(RefType clintedType | c = clintedType.getASupertype*().getACallable() |
result.getDeclaringType() = clintedType or
result.getAnAccessedField().getDeclaringType() = clintedType
)
c.hasName("<clinit>") and
reason = "class initialization" and
exists(RefType clintedType | c = clintedType.getASupertype*().getACallable() |
result.getDeclaringType() = clintedType or
result.getAnAccessedField().getDeclaringType() = clintedType
)
or
(
c.hasName("<obinit>") and
reason = "object initialization" and
result = c.getDeclaringType().getAConstructor()
)
c.hasName("<obinit>") and
reason = "object initialization" and
result = c.getDeclaringType().getAConstructor()
}
Callable possibleLivenessCause(Callable c) { result = possibleLivenessCause(c, _) }
@@ -91,7 +85,7 @@ class SuppressedConstructor extends Constructor {
isPrivate()
or
// A protected, suppressed constructor only makes sense in a non-abstract class.
(isProtected() and not getDeclaringType().isAbstract())
isProtected() and not getDeclaringType().isAbstract()
) and
// Must be no-arg in order to replace the compiler generated default constructor.
getNumberOfParameters() = 0 and
@@ -167,13 +161,11 @@ class LiveClass extends SourceClassOrInterface {
not f instanceof SerialVersionUIDField
)
or
(
// If this is a namespace class, it is live if there is at least one live nested class.
// The definition of `NamespaceClass` is such, that the nested classes must all be static.
// Static methods are handled above.
this instanceof NamespaceClass and
exists(NestedType r | r.getEnclosingType() = this | r instanceof LiveClass)
)
// If this is a namespace class, it is live if there is at least one live nested class.
// The definition of `NamespaceClass` is such, that the nested classes must all be static.
// Static methods are handled above.
this instanceof NamespaceClass and
exists(NestedType r | r.getEnclosingType() = this | r instanceof LiveClass)
or
// An annotation on the class is reflectively accessed.
exists(ReflectiveAnnotationAccess reflectiveAnnotationAccess |
@@ -298,10 +290,8 @@ class RootdefCallable extends Callable {
// Abstract, native and interface methods obviously won't access their own
// parameters, so don't flag unless we can see an overriding method with
// a body that also doesn't.
(
not hasUsefulBody(this) and
not exists(Method m | hasUsefulBody(m) | m.overridesOrInstantiates+(this))
)
not hasUsefulBody(this) and
not exists(Method m | hasUsefulBody(m) | m.overridesOrInstantiates+(this))
}
}

View File

@@ -22,10 +22,8 @@ class Struts1ActionEntryPoint extends EntryPoint, Class {
result.(Method).overrides(methodFromAction)
)
or
(
this.getASupertype*().hasQualifiedName("org.apache.struts.actions", "DispatchAction") and
result.(Method).isPublic()
)
this.getASupertype*().hasQualifiedName("org.apache.struts.actions", "DispatchAction") and
result.(Method).isPublic()
or
result.(Constructor).getNumberOfParameters() = 0
)

View File

@@ -10,11 +10,9 @@ import semmle.code.java.UnitTests
*/
class TestMethodEntry extends CallableEntryPoint {
TestMethodEntry() {
(
this instanceof TestMethod and
// Ignored tests are not run
not this instanceof JUnitIgnoredMethod
)
this instanceof TestMethod and
// Ignored tests are not run
not this instanceof JUnitIgnoredMethod
or
this instanceof JUnit3TestSuite
or

View File

@@ -62,7 +62,7 @@ class JaxbType extends Class {
* Gets the `XmlAccessType` associated with this class.
*/
XmlAccessType getXmlAccessType() {
if (exists(getDeclaredAccessType()))
if exists(getDeclaredAccessType())
then result = getDeclaredAccessType()
else
// Default access type, if not specified.
@@ -136,7 +136,7 @@ class JaxbBoundField extends Field {
type.getXmlAccessType().isField()
or
// Only public fields are automatically bound in this access type.
(type.getXmlAccessType().isPublicMember() and isPublic())
type.getXmlAccessType().isPublicMember() and isPublic()
)
)
}
@@ -192,7 +192,7 @@ class JaxbBoundGetterSetter extends GetterOrSetterMethod {
isProperty() and
(
// In the `PUBLIC_MEMBER` case all public properties are considered bound.
(c.getXmlAccessType().isPublicMember() and isPublic())
c.getXmlAccessType().isPublicMember() and isPublic()
or
// In "property" all properties are considered bound.
c.getXmlAccessType().isProperty()

View File

@@ -15,11 +15,9 @@ class JaxWsEndpoint extends Class {
Callable getARemoteMethod() {
result = this.getACallable() and
(
exists(AnnotationType a | a = result.getAnAnnotation().getType() |
a.hasName("WebMethod") or
a.hasName("WebEndpoint")
)
exists(AnnotationType a | a = result.getAnAnnotation().getType() |
a.hasName("WebMethod") or
a.hasName("WebEndpoint")
)
}
}

View File

@@ -222,24 +222,20 @@ class MockitoInjectedField extends MockitoAnnotatedField {
else
if usingPropertyInjection()
then
(
// We will call the no-arg constructor if the field wasn't initialized.
not exists(getInitializer()) and
result = mockInjectedClass.getNoArgsConstructor()
)
// We will call the no-arg constructor if the field wasn't initialized.
not exists(getInitializer()) and
result = mockInjectedClass.getNoArgsConstructor()
or
(
// Perform property injection into setter fields, but only where there exists a mock
// that can be injected into the method. Otherwise, the setter method is never called.
result = mockInjectedClass.getASetterMethod() and
exists(MockitoMockedField mockedField |
mockedField.getDeclaringType() = this.getDeclaringType() and
mockedField.isValid()
|
// We make a simplifying assumption here - in theory, each mock can only be injected
// once, but we instead assume that there are sufficient mocks to go around.
mockedField.getType().(RefType).getAnAncestor() = result.getParameterType(0)
)
// Perform property injection into setter fields, but only where there exists a mock
// that can be injected into the method. Otherwise, the setter method is never called.
result = mockInjectedClass.getASetterMethod() and
exists(MockitoMockedField mockedField |
mockedField.getDeclaringType() = this.getDeclaringType() and
mockedField.isValid()
|
// We make a simplifying assumption here - in theory, each mock can only be injected
// once, but we instead assume that there are sufficient mocks to go around.
mockedField.getType().(RefType).getAnAncestor() = result.getParameterType(0)
)
else
// There's no instance, and no no-arg constructor we can call, so injection fails.

View File

@@ -30,10 +30,8 @@ class SafeSnakeYamlConstruction extends ClassInstanceExpr {
SafeSnakeYamlConstruction() {
this.getConstructedType() instanceof SnakeYamlSafeConstructor
or
(
this.getConstructedType() instanceof SnakeYamlConstructor and
this.getNumArgument() > 0
)
this.getConstructedType() instanceof SnakeYamlConstructor and
this.getNumArgument() > 0
}
}

View File

@@ -35,10 +35,8 @@ class GwtEntryPointClass extends Class {
// are live.
isGwtXmlIncluded()
implies
(
// The entry point is live if it is specified in a `*.gwt.xml` file.
exists(getAGwtXmlFile())
)
// The entry point is live if it is specified in a `*.gwt.xml` file.
exists(getAGwtXmlFile())
}
}

View File

@@ -39,7 +39,7 @@ class GwtXmlFile extends XMLFile {
* Either the default `client` folder or as specified by `<source>` tags.
*/
string getASourceSubPath() {
(result = "client" and not exists(getAnExplicitSourceSubPath()))
result = "client" and not exists(getAnExplicitSourceSubPath())
or
result = getAnExplicitSourceSubPath()
}

View File

@@ -68,7 +68,7 @@ class SessionEJB extends EJB {
/** Any remote interfaces of this EJB. */
LegacyEjbRemoteInterface getARemoteInterface() {
(result = this.getASupertype() and result instanceof ExtendedRemoteInterface)
result = this.getASupertype() and result instanceof ExtendedRemoteInterface
or
exists(AnnotatedRemoteHomeInterface i | i.getAnEJB() = this |
result = i.getAnAssociatedRemoteInterface()
@@ -79,7 +79,7 @@ class SessionEJB extends EJB {
/** Any remote home interfaces of this EJB. */
LegacyEjbRemoteHomeInterface getARemoteHomeInterface() {
(result = this.getASupertype() and result instanceof ExtendedRemoteHomeInterface)
result = this.getASupertype() and result instanceof ExtendedRemoteHomeInterface
or
result.(AnnotatedRemoteHomeInterface).getAnEJB() = this
or
@@ -88,7 +88,7 @@ class SessionEJB extends EJB {
/** Any local interfaces of this EJB. */
LegacyEjbLocalInterface getALocalInterface() {
(result = this.getASupertype() and result instanceof ExtendedLocalInterface)
result = this.getASupertype() and result instanceof ExtendedLocalInterface
or
exists(AnnotatedLocalHomeInterface i | i.getAnEJB() = this |
result = i.getAnAssociatedLocalInterface()
@@ -99,7 +99,7 @@ class SessionEJB extends EJB {
/** Any local home interfaces of this EJB. */
LegacyEjbLocalHomeInterface getALocalHomeInterface() {
(result = this.getASupertype() and result instanceof ExtendedLocalHomeInterface)
result = this.getASupertype() and result instanceof ExtendedLocalHomeInterface
or
result.(AnnotatedLocalHomeInterface).getAnEJB() = this
or
@@ -898,10 +898,8 @@ TransactionAttributeAnnotation getInnermostTransactionAttributeAnnotation(Method
or
// ...or if the declaring class has such an annotation, the annotation applies to
// any method declared within the class that does not itself have such an annotation.
(
not exists(m.getAnAnnotation().(TransactionAttributeAnnotation)) and
result = m.getDeclaringType().getSourceDeclaration().getAnAnnotation()
)
not exists(m.getAnAnnotation().(TransactionAttributeAnnotation)) and
result = m.getDeclaringType().getSourceDeclaration().getAnAnnotation()
}
/*

View File

@@ -78,30 +78,24 @@ class SpringBeanXMLAutowiredSetterMethod extends Method {
exists(string xmlAutowire |
xmlAutowire = this.getDeclaringType().(SpringBeanRefType).getSpringBean().getAutowire()
|
(
xmlAutowire = "byName" and
// There is a bean whose name is the same as this setter method.
this.getName().toLowerCase() = "set" + result.getBeanIdentifier().toLowerCase()
)
xmlAutowire = "byName" and
// There is a bean whose name is the same as this setter method.
this.getName().toLowerCase() = "set" + result.getBeanIdentifier().toLowerCase()
or
(
(
xmlAutowire = "byType"
or
(
// When it is set to autodetect, we use "byType" if there is a no-arg constructor. This
// approach has been removed in Spring 4.x.
xmlAutowire = "autodetect" and
exists(Constructor c | c = this.getDeclaringType().getAConstructor() |
c.getNumberOfParameters() = 0
)
)
) and
// The resulting bean is of the right type.
result.getClass().getAnAncestor() = getParameter(0).getType() and
getNumberOfParameters() = 1 and
this.getName().matches("set%")
)
xmlAutowire = "byType"
or
// When it is set to autodetect, we use "byType" if there is a no-arg constructor. This
// approach has been removed in Spring 4.x.
xmlAutowire = "autodetect" and
exists(Constructor c | c = this.getDeclaringType().getAConstructor() |
c.getNumberOfParameters() = 0
)
) and
// The resulting bean is of the right type.
result.getClass().getAnAncestor() = getParameter(0).getType() and
getNumberOfParameters() = 1 and
this.getName().matches("set%")
)
}
}
@@ -166,17 +160,17 @@ class SpringBeanAutowiredCallable extends Callable {
result = getQualifier(pos).getSpringBean()
else
if exists(getQualifier()) and getNumberOfParameters() = 1
then (
then
// Resolved by `@Qualifier("qualifier")` on the method
pos = 0 and
result = getQualifier().getSpringBean()
) else
else
if exists(getResource().getNameValue()) and getNumberOfParameters() = 1
then (
then
// Resolved by looking at the name part of `@Resource(name="qualifier")`
pos = 0 and
result = getResource().getSpringBean()
) else
else
// Otherwise no restrictions, just by type
any()
}
@@ -195,17 +189,17 @@ class SpringBeanAutowiredCallable extends Callable {
result = getQualifier(pos).getSpringComponent()
else
if exists(getQualifier()) and getNumberOfParameters() = 1
then (
then
// Resolved by `@Qualifier("qualifier")` on the method
pos = 0 and
result = getQualifier().getSpringComponent()
) else
else
if exists(getResource().getNameValue()) and getNumberOfParameters() = 1
then (
then
// Resolved by looking at the name part of `@Resource(name="qualifier")`
pos = 0 and
result = getResource().getSpringComponent()
) else
else
// Otherwise no restrictions, just by type
any()
}

View File

@@ -279,11 +279,9 @@ class SpringBean extends SpringXMLElement {
/** Any `<property>` elements inherited from parent beans. */
SpringProperty getAnInheritedProperty() {
(
not exists(SpringProperty thisProperty |
thisProperty = this.getADeclaredProperty() and
result.getPropertyName() = thisProperty.getPropertyName()
)
not exists(SpringProperty thisProperty |
thisProperty = this.getADeclaredProperty() and
result.getPropertyName() = thisProperty.getPropertyName()
) and
(
result = this.getBeanParent().getADeclaredProperty() or
@@ -305,11 +303,9 @@ class SpringBean extends SpringXMLElement {
/** Gets a `<constructor-arg>` element inherited from the parent bean. */
SpringConstructorArg getAnInheritedConstructorArg() {
(
not exists(SpringConstructorArg thisArg |
thisArg = this.getADeclaredConstructorArg() and
thisArg.conflictsWithArg(result)
)
not exists(SpringConstructorArg thisArg |
thisArg = this.getADeclaredConstructorArg() and
thisArg.conflictsWithArg(result)
) and
(
result = this.getBeanParent().getADeclaredConstructorArg() or
@@ -331,11 +327,9 @@ class SpringBean extends SpringXMLElement {
/** Gets a `<lookup-method>` element inherited from the parent bean. */
SpringLookupMethod getAnInheritedLookupMethod() {
(
not exists(SpringLookupMethod thisMethod |
thisMethod = this.getADeclaredLookupMethod() and
thisMethod.getMethodName() = result.getMethodName()
)
not exists(SpringLookupMethod thisMethod |
thisMethod = this.getADeclaredLookupMethod() and
thisMethod.getMethodName() = result.getMethodName()
) and
(
result = this.getBeanParent().getADeclaredLookupMethod() or
@@ -357,11 +351,9 @@ class SpringBean extends SpringXMLElement {
/** Gets a `<replaced-method>` element inherited from the parent bean. */
SpringReplacedMethod getAnInheritedReplacedMethod() {
(
not exists(SpringReplacedMethod thisMethod |
thisMethod = this.getADeclaredReplacedMethod() and
thisMethod.getMethodName() = result.getMethodName()
)
not exists(SpringReplacedMethod thisMethod |
thisMethod = this.getADeclaredReplacedMethod() and
thisMethod.getMethodName() = result.getMethodName()
) and
(
result = this.getBeanParent().getADeclaredReplacedMethod() or

View File

@@ -178,15 +178,13 @@ class SpringComponent extends RefType {
// package.
not isSpringXMLEnabled()
or
exists(SpringBasePackage sbp |
this.getPackage().getName().prefix(sbp.length() + 1) = sbp + "." or
this.getPackage().getName() = sbp
) and
(
exists(SpringBasePackage sbp |
this.getPackage().getName().prefix(sbp.length() + 1) = sbp + "." or
this.getPackage().getName() = sbp
) and
(
not exists(getAProfileExpr()) or
getAProfileExpr().(SpringProfileExpr).isActive()
)
not exists(getAProfileExpr()) or
getAProfileExpr().(SpringProfileExpr).isActive()
)
}

View File

@@ -44,13 +44,11 @@ class SpringRemotingDestinationClass extends Class {
this = remotingDestination.getSpringBean().getClass()
)
or
hasAnnotation("org.springframework.flex.remoting", "RemotingDestination") and
// Must either be a live bean, or a live component.
(
hasAnnotation("org.springframework.flex.remoting", "RemotingDestination") and
// Must either be a live bean, or a live component.
(
this.(SpringComponent).isLive() or
this instanceof SpringBeanRefType
)
this.(SpringComponent).isLive() or
this instanceof SpringBeanRefType
)
}

View File

@@ -14,12 +14,10 @@ private string getStrutsMapperClass(RefType refType) {
*/
class Struts2ActionClass extends Class {
Struts2ActionClass() {
(
// If there are no XML files present, then we assume we any class that extends a struts 2
// action must be reflectively constructed, as we have no better indication.
not exists(XMLFile xmlFile) and
this.getAnAncestor().hasQualifiedName("com.opensymphony.xwork2", "Action")
)
// If there are no XML files present, then we assume we any class that extends a struts 2
// action must be reflectively constructed, as we have no better indication.
not exists(XMLFile xmlFile) and
this.getAnAncestor().hasQualifiedName("com.opensymphony.xwork2", "Action")
or
// If there is a struts.xml file, then any class that is specified as an action is considered
// to be reflectively constructed.
@@ -37,7 +35,7 @@ class Struts2ActionClass extends Class {
if
getStrutsMapperClass(this) = "org.apache.struts2.dispatcher.mapper.Restful2ActionMapper" or
getStrutsMapperClass(this) = "org.apache.struts2.dispatcher.mapper.RestfulActionMapper"
then (
then
// The "Restful" action mapper maps rest APIs to specific methods
result.hasName("index") or
result.hasName("create") or
@@ -45,11 +43,11 @@ class Struts2ActionClass extends Class {
result.hasName("view") or
result.hasName("remove") or
result.hasName("update")
) else
else
if
getStrutsMapperClass(this) = "org.apache.struts2.rest.RestActionMapper" or
getStrutsMapperClass(this) = "rest"
then (
then
// The "Rest" action mapper is provided with the rest plugin, and maps rest APIs to specific
// methods based on a "ruby-on-rails" style.
result.hasName("index") or
@@ -59,7 +57,7 @@ class Struts2ActionClass extends Class {
result.hasName("create") or
result.hasName("update") or
result.hasName("destroy")
) else
else
if exists(getStrutsMapperClass(this))
then
// Any method could be live, as this is a custom mapper
@@ -73,14 +71,12 @@ class Struts2ActionClass extends Class {
or
result = this.(Struts2ConventionActionClass).getAnActionMethod()
or
// In the fall-back case, use both the "execute" and any annotated methods
not exists(XMLFile xmlFile) and
(
// In the fall-back case, use both the "execute" and any annotated methods
not exists(XMLFile xmlFile) and
(
result.hasName("executes") or
exists(StrutsActionAnnotation actionAnnotation |
result = actionAnnotation.getActionCallable()
)
result.hasName("executes") or
exists(StrutsActionAnnotation actionAnnotation |
result = actionAnnotation.getActionCallable()
)
)
)

View File

@@ -142,7 +142,7 @@ private string escapeForMatch(string s) { result = s.replaceAll("%", "\\%").repl
*/
bindingset[matches, wildcardstring]
private predicate strutsWildcardMatching(string matches, string wildcardstring) {
if (wildcardstring.matches("%{%}%"))
if wildcardstring.matches("%{%}%")
then matches.matches(escapeForMatch(wildcardstring).regexpReplaceAll("\\{[0-9]\\}", "%"))
else matches = wildcardstring
}
@@ -169,7 +169,7 @@ class StrutsXMLAction extends StrutsXMLElement {
*/
Method getActionMethod() {
getActionClass().inherits(result) and
if (exists(getMethodName()))
if exists(getMethodName())
then strutsWildcardMatching(result.getName(), getMethodName())
else result.hasName("execute")
}

View File

@@ -41,20 +41,16 @@ class MetricElement extends Element {
*/
int getALevel() {
this.fromSource() and
not (this.getADependencySrc+() = this) and
not this.getADependencySrc+() = this and
(
(
not (exists(MetricElement t | t = this.getADependency())) and
result = 0
)
not exists(MetricElement t | t = this.getADependency()) and
result = 0
or
(
not (this.getADependency().fromSource()) and
exists(MetricElement e | this.getADependency() = e) and
result = 1
)
not this.getADependency().fromSource() and
exists(MetricElement e | this.getADependency() = e) and
result = 1
or
(result = this.getADependency().getALevel() + 1)
result = this.getADependency().getALevel() + 1
)
}

View File

@@ -61,8 +61,8 @@ class MetricPackage extends Package, MetricElement {
*/
int getNumberOfPublicCallables() {
result = sum(MetricRefType t, int toSum |
(t.getPackage() = this) and
(toSum = t.getNumberOfPublicCallables())
t.getPackage() = this and
toSum = t.getNumberOfPublicCallables()
|
toSum
)
@@ -138,7 +138,7 @@ class MetricPackage extends Package, MetricElement {
ecoupling = this.getEfferentCoupling() and
sumcoupling = ecoupling + this.getAfferentCoupling() and
sumcoupling > 0 and
result = ecoupling / (sumcoupling.(float))
result = ecoupling / sumcoupling.(float)
)
}
@@ -164,7 +164,7 @@ class MetricPackage extends Package, MetricElement {
exists(int i, int j |
i = count(RefType t | t.getPackage() = this) and
j = count(RefType t | t.getPackage() = this and t.isAbstract()) and
result = j / (i.(float)) and
result = j / i.(float) and
i > 0
)
}
@@ -221,8 +221,8 @@ class MetricPackage extends Package, MetricElement {
float relationalCohesion() {
result = 1 +
avg(RefType t, float toAvg |
(t.getPackage() = this) and
(toAvg = this.countDependencies(t))
t.getPackage() = this and
toAvg = this.countDependencies(t)
|
toAvg
)
@@ -265,8 +265,8 @@ class MetricPackage extends Package, MetricElement {
*/
predicate isRepresentative() {
this.getName() = min(MetricPackage p, string toMin |
(p = this.getACycleMember()) and
(toMin = p.getName())
p = this.getACycleMember() and
toMin = p.getName()
|
toMin
)
@@ -280,7 +280,7 @@ class MetricPackage extends Package, MetricElement {
float getAverageFanIn() {
result = avg(RefType t, MetricCallable c, int toAvg |
(c = t.getACallable() and t.getPackage() = this) and
(toAvg = c.getAfferentCoupling())
toAvg = c.getAfferentCoupling()
|
toAvg
)

View File

@@ -198,18 +198,18 @@ class MetricRefType extends RefType, MetricElement {
// is `C`, is `(C - 1) * C`.
n = (((callables - 1) * callables) - (2 * linked)) / 2.0 and
(
(n < 0 and result = 0)
n < 0 and result = 0
or
(n >= 0 and result = n)
n >= 0 and result = n
)
)
}
/** Gets the length of _some_ path to the root of the hierarchy. */
int getADepth() {
(this.hasQualifiedName("java.lang", "Object") and result = 0)
this.hasQualifiedName("java.lang", "Object") and result = 0
or
(not cyclic() and result = this.getASupertype().(MetricRefType).getADepth() + 1)
not cyclic() and result = this.getASupertype().(MetricRefType).getADepth() + 1
}
/**
@@ -229,9 +229,9 @@ class MetricRefType extends RefType, MetricElement {
/** Gets the length of _some_ path to the specified reference type. */
int getADepth(RefType reference) {
(this = reference and result = 0)
this = reference and result = 0
or
(not cyclic() and result = this.getASupertype().(MetricRefType).getADepth(reference) + 1)
not cyclic() and result = this.getASupertype().(MetricRefType).getADepth(reference) + 1
}
private predicate cyclic() { getASupertype+() = this }
@@ -278,9 +278,9 @@ class MetricRefType extends RefType, MetricElement {
this.getAMethod() = result and
exists(Method c |
result.overrides(c) and
not (c.isAbstract())
not c.isAbstract()
) and
not (this.ignoreOverride(result))
not this.ignoreOverride(result)
}
/** Gets the number of methods that are overridden by this class. */
@@ -297,14 +297,14 @@ class MetricRefType extends RefType, MetricElement {
float getSpecialisationIndex() {
this.getNumberOfCallables() != 0 and
result = (this.getNumberOverridden() * this.getInheritanceDepth()) /
(this.getNumberOfCallables().(float))
this.getNumberOfCallables().(float)
}
/** Gets the Halstead length of a type, estimated as the sum of the Halstead lengths of its callables. */
override int getHalsteadLength() {
result = sum(Callable c, int toSum |
(c = this.getACallable()) and
(toSum = c.getMetrics().getHalsteadLength())
c = this.getACallable() and
toSum = c.getMetrics().getHalsteadLength()
|
toSum
)
@@ -313,8 +313,8 @@ class MetricRefType extends RefType, MetricElement {
/** Gets the Halstead vocabulary of a type, estimated as the sum of the Halstead vocabularies of its callables. */
override int getHalsteadVocabulary() {
result = sum(Callable c, int toSum |
(c = this.getACallable()) and
(toSum = c.getMetrics().getHalsteadVocabulary())
c = this.getACallable() and
toSum = c.getMetrics().getHalsteadVocabulary()
|
toSum
)
@@ -323,8 +323,8 @@ class MetricRefType extends RefType, MetricElement {
/** Gets the cyclomatic complexity of a type, estimated as the sum of the cyclomatic complexities of its callables. */
override int getCyclomaticComplexity() {
result = sum(Callable c, int toSum |
(c = this.getACallable()) and
(toSum = c.getMetrics().getCyclomaticComplexity())
c = this.getACallable() and
toSum = c.getMetrics().getCyclomaticComplexity()
|
toSum
)

View File

@@ -73,17 +73,13 @@ deprecated class FlowSource extends Expr {
not isExcluded(tracked)
|
// Flow within a single method.
(
flowsTo(tracked, fromArg) and
localFlowStep(tracked, sink)
)
flowsTo(tracked, fromArg) and
localFlowStep(tracked, sink)
or
// Flow through a field.
(
flowsTo(tracked, _) and
staticFieldStep(tracked, sink) and
fromArg = false
)
flowsTo(tracked, _) and
staticFieldStep(tracked, sink) and
fromArg = false
or
// Flow through a method that returns one of its arguments.
exists(MethodAccess call, int i |
@@ -104,11 +100,9 @@ deprecated class FlowSource extends Expr {
// Flow out of a method.
// This path is only enabled if the flow did not come from the argument;
// such cases are handled by `methodReturnsArg`.
(
flowsTo(tracked, false) and
methodStep(tracked, sink) and
fromArg = false
)
flowsTo(tracked, false) and
methodStep(tracked, sink) and
fromArg = false
)
}
@@ -170,10 +164,8 @@ deprecated private Callable responderForArg(Call call, int i, FlowExpr tracked)
deprecated private Callable responder(Call call) {
result = exactCallable(call)
or
(
not exists(exactCallable(call)) and
result = call.getCallee()
)
not exists(exactCallable(call)) and
result = call.getCallee()
}
/** Holds if a method can return its argument. This is public for testing. */
@@ -240,7 +232,7 @@ deprecated private predicate localFlowStep(Expr tracked, Expr sink) {
argToMethodStep(tracked, sink)
or
// An unsafe attempt to escape tainted input.
(unsafeEscape(sink) and sink.(MethodAccess).getQualifier() = tracked)
unsafeEscape(sink) and sink.(MethodAccess).getQualifier() = tracked
or
// A logic expression.
sink.(LogicExpr).getAnOperand() = tracked
@@ -349,9 +341,9 @@ deprecated private predicate comparisonStep(Expr tracked, Expr sink) {
exists(MethodAccess m | m.getMethod() instanceof EqualsMethod |
m = sink and
(
(m.getQualifier() = tracked and m.getArgument(0) = other)
m.getQualifier() = tracked and m.getArgument(0) = other
or
(m.getQualifier() = other and m.getArgument(0) = tracked)
m.getQualifier() = other and m.getArgument(0) = tracked
)
)
) and
@@ -605,74 +597,54 @@ deprecated predicate qualifierToMethodStep(Expr tracked, MethodAccess sink) {
*/
deprecated class DataPreservingMethod extends Method {
DataPreservingMethod() {
this.getDeclaringType() instanceof TypeString and
(
this.getDeclaringType() instanceof TypeString and
(
this.getName() = "endsWith" or
this.getName() = "getBytes" or
this.getName() = "split" or
this.getName() = "substring" or
this.getName() = "toCharArray" or
this.getName() = "toLowerCase" or
this.getName() = "toString" or
this.getName() = "toUpperCase" or
this.getName() = "trim"
)
this.getName() = "endsWith" or
this.getName() = "getBytes" or
this.getName() = "split" or
this.getName() = "substring" or
this.getName() = "toCharArray" or
this.getName() = "toLowerCase" or
this.getName() = "toString" or
this.getName() = "toUpperCase" or
this.getName() = "trim"
)
or
exists(Class c | c.getQualifiedName() = "java.lang.Number" |
hasSubtypeStar(c, this.getDeclaringType())
) and
(
exists(Class c | c.getQualifiedName() = "java.lang.Number" |
hasSubtypeStar(c, this.getDeclaringType())
) and
(
this.getName().matches("to%String") or
this.getName() = "toByteArray" or
this.getName().matches("%Value")
)
this.getName().matches("to%String") or
this.getName() = "toByteArray" or
this.getName().matches("%Value")
)
or
(
this.getDeclaringType().getQualifiedName().matches("%Reader") and
this.getName().matches("read%")
)
this.getDeclaringType().getQualifiedName().matches("%Reader") and
this.getName().matches("read%")
or
this.getDeclaringType().getQualifiedName().matches("%StringWriter") and
this.getName() = "toString"
or
this.getDeclaringType().hasQualifiedName("java.util", "StringTokenizer") and
this.getName().matches("next%")
or
this.getDeclaringType().hasQualifiedName("java.io", "ByteArrayOutputStream") and
(this.getName() = "toByteArray" or this.getName() = "toString")
or
this.getDeclaringType().hasQualifiedName("java.io", "ObjectInputStream") and
this.getName().matches("read%")
or
(
this.getDeclaringType().getQualifiedName().matches("%StringWriter") and
this.getName() = "toString"
)
this.getDeclaringType().hasQualifiedName("java.lang", "StringBuilder") or
this.getDeclaringType().hasQualifiedName("java.lang", "StringBuffer")
) and
(this.getName() = "toString" or this.getName() = "append")
or
(
this.getDeclaringType().hasQualifiedName("java.util", "StringTokenizer") and
this.getName().matches("next%")
)
this.getDeclaringType().hasQualifiedName("javax.xml.transform.sax", "SAXSource") and
this.hasName("getInputSource")
or
(
this.getDeclaringType().hasQualifiedName("java.io", "ByteArrayOutputStream") and
(this.getName() = "toByteArray" or this.getName() = "toString")
)
or
(
this.getDeclaringType().hasQualifiedName("java.io", "ObjectInputStream") and
this.getName().matches("read%")
)
or
(
(
this.getDeclaringType().hasQualifiedName("java.lang", "StringBuilder") or
this.getDeclaringType().hasQualifiedName("java.lang", "StringBuffer")
) and
(this.getName() = "toString" or this.getName() = "append")
)
or
(
this.getDeclaringType().hasQualifiedName("javax.xml.transform.sax", "SAXSource") and
this.hasName("getInputSource")
)
or
(
this.getDeclaringType().hasQualifiedName("javax.xml.transform.stream", "StreamSource") and
this.hasName("getInputStream")
)
this.getDeclaringType().hasQualifiedName("javax.xml.transform.stream", "StreamSource") and
this.hasName("getInputStream")
}
}
@@ -681,89 +653,75 @@ deprecated class DataPreservingMethod extends Method {
* is tainted.
*/
deprecated predicate dataPreservingArgument(Method method, int arg) {
method instanceof StringReplaceMethod and
arg = 1
or
exists(Class c | c.getQualifiedName() = "java.lang.Number" |
hasSubtypeStar(c, method.getDeclaringType())
) and
(
method instanceof StringReplaceMethod and
arg = 1
method.getName().matches("parse%") and arg = 0
or
method.getName().matches("valueOf%") and arg = 0
or
method.getName().matches("to%String") and arg = 0
)
or
(
exists(Class c | c.getQualifiedName() = "java.lang.Number" |
hasSubtypeStar(c, method.getDeclaringType())
) and
(
(method.getName().matches("parse%") and arg = 0)
or
(method.getName().matches("valueOf%") and arg = 0)
or
(method.getName().matches("to%String") and arg = 0)
)
method.getDeclaringType().hasQualifiedName("java.lang", "StringBuilder") or
method.getDeclaringType().hasQualifiedName("java.lang", "StringBuffer")
) and
(
method.getName() = "append" and arg = 0
or
method.getName() = "insert" and arg = 1
or
method.getName() = "replace" and arg = 2
)
or
(
(
method.getDeclaringType().hasQualifiedName("java.lang", "StringBuilder") or
method.getDeclaringType().hasQualifiedName("java.lang", "StringBuffer")
) and
(
method.getName() = "append" and arg = 0
or
method.getName() = "insert" and arg = 1
or
method.getName() = "replace" and arg = 2
)
method.getDeclaringType().hasQualifiedName("java.util", "Base64$Encoder") or
method.getDeclaringType().hasQualifiedName("java.util", "Base64$Decoder")
) and
(
method.getName() = "encode" and arg = 0 and method.getNumberOfParameters() = 1
or
method.getName() = "decode" and arg = 0 and method.getNumberOfParameters() = 1
or
method.getName() = "encodeToString" and arg = 0
or
method.getName() = "wrap" and arg = 0
)
or
method.getDeclaringType().hasQualifiedName("org.apache.commons.io", "IOUtils") and
(
(
method.getDeclaringType().hasQualifiedName("java.util", "Base64$Encoder") or
method.getDeclaringType().hasQualifiedName("java.util", "Base64$Decoder")
) and
(
method.getName() = "encode" and arg = 0 and method.getNumberOfParameters() = 1
or
method.getName() = "decode" and arg = 0 and method.getNumberOfParameters() = 1
or
method.getName() = "encodeToString" and arg = 0
or
method.getName() = "wrap" and arg = 0
)
method.getName() = "buffer" and arg = 0
or
method.getName() = "readLines" and arg = 0
or
method.getName() = "readFully" and arg = 0 and method.getParameterType(1).hasName("int")
or
method.getName() = "toBufferedInputStream" and arg = 0
or
method.getName() = "toBufferedReader" and arg = 0
or
method.getName() = "toByteArray" and arg = 0
or
method.getName() = "toCharArray" and arg = 0
or
method.getName() = "toInputStream" and arg = 0
or
method.getName() = "toString" and arg = 0
)
or
(
(method.getDeclaringType().hasQualifiedName("org.apache.commons.io", "IOUtils")) and
(
method.getName() = "buffer" and arg = 0
or
method.getName() = "readLines" and arg = 0
or
method.getName() = "readFully" and arg = 0 and method.getParameterType(1).hasName("int")
or
method.getName() = "toBufferedInputStream" and arg = 0
or
method.getName() = "toBufferedReader" and arg = 0
or
method.getName() = "toByteArray" and arg = 0
or
method.getName() = "toCharArray" and arg = 0
or
method.getName() = "toInputStream" and arg = 0
or
method.getName() = "toString" and arg = 0
)
)
//A URI created from a tainted string is still tainted.
method.getDeclaringType().hasQualifiedName("java.net", "URI") and
method.hasName("create") and
arg = 0
or
(
//A URI created from a tainted string is still tainted.
method.getDeclaringType().hasQualifiedName("java.net", "URI") and
method.hasName("create") and
arg = 0
)
or
(
method.getDeclaringType().hasQualifiedName("javax.xml.transform.sax", "SAXSource") and
method.hasName("sourceToInputSource") and
arg = 0
)
method.getDeclaringType().hasQualifiedName("javax.xml.transform.sax", "SAXSource") and
method.hasName("sourceToInputSource") and
arg = 0
}
deprecated class StringReplaceMethod extends Method {

View File

@@ -44,17 +44,13 @@ private EnumConstant getAContainedEnumConstant(Expr enumSetRef) {
exists(MethodAccess addToSet |
addToSet.getQualifier() = enumSetAccess.getVariable().getAnAccess()
|
(
// Call to `add(..)` on the enum set variable.
addToSet.getMethod().hasName("add") and
result = addToSet.getArgument(0).(VarAccess).getVariable()
)
// Call to `add(..)` on the enum set variable.
addToSet.getMethod().hasName("add") and
result = addToSet.getArgument(0).(VarAccess).getVariable()
or
(
// Call to `addAll(..)` on the enum set variable.
addToSet.getMethod().hasName("addAll") and
result = getAContainedEnumConstant(addToSet.getArgument(0))
)
// Call to `addAll(..)` on the enum set variable.
addToSet.getMethod().hasName("addAll") and
result = getAContainedEnumConstant(addToSet.getArgument(0))
)
)
)

View File

@@ -148,11 +148,9 @@ abstract class ReturnsPredictableExpr extends Method { }
class ReturnsSystemTime extends ReturnsPredictableExpr {
ReturnsSystemTime() {
(
this.getDeclaringType().hasQualifiedName("java.lang", "System") and
this.hasName("currentTimeMillis")
)
this.getDeclaringType().hasQualifiedName("java.lang", "System") and
this.hasName("currentTimeMillis")
or
(this.getDeclaringType().hasQualifiedName("java.lang", "System") and this.hasName("nanoTime"))
this.getDeclaringType().hasQualifiedName("java.lang", "System") and this.hasName("nanoTime")
}
}

View File

@@ -59,7 +59,7 @@ class Pom extends ProtoPom {
override Group getGroup() {
// For a project element, the group may be defined in the parent tags instead
if not (exists(super.getGroup()))
if not exists(super.getGroup())
then exists(Parent p | p = this.getAChild() and result = p.getAChild())
else result = super.getGroup()
}
@@ -94,10 +94,8 @@ class Pom extends ProtoPom {
PomProperty getAProperty() {
result = getALocalProperty()
or
(
result = getParentPom().getAProperty() and
not getALocalProperty().getName() = result.getName()
)
result = getParentPom().getAProperty() and
not getALocalProperty().getName() = result.getName()
}
/**
@@ -116,11 +114,9 @@ class Pom extends ProtoPom {
// It must either be a child of the pom, or a child of the parent node of the pom
result = getAChild()
or
(
result = getParentPom().getAChild() and
// The parent project property is not shadowed by a local project property
not exists(PomElement p | p = getAChild() and p.getName() = result.getName())
)
result = getParentPom().getAChild() and
// The parent project property is not shadowed by a local project property
not exists(PomElement p | p = getAChild() and p.getName() = result.getName())
) and
// Can't be a property if it has children of its own
not exists(result.getAChild())

View File

@@ -142,15 +142,11 @@ class XMLDTD extends @xmldtd {
/** Gets a printable representation of this DTD. */
string toString() {
(
this.isPublic() and
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
)
this.isPublic() and
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
or
(
not this.isPublic() and
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
)
not this.isPublic() and
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
}
}
@@ -233,9 +229,9 @@ class XMLNamespace extends @xmlnamespace {
/** Gets a printable representation of this XML namespace. */
string toString() {
(this.isDefault() and result = this.getURI())
this.isDefault() and result = this.getURI()
or
(not this.isDefault() and result = this.getPrefix() + ":" + this.getURI())
not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()
}
}