Files
codeql/java/ql/src/Language Abuse/UselessUpcast.ql
Ian Lynagh 6566f7b69f Kotlin: Add types for the different kinds of casts that Kotlin has
We might want to unify some of these in future, but doing that
correctly is easier than splitting them up correctly, so I've given each
one its own QL class for now.

I am not familiar with many of the libraries/queries that use CastExpr.
I've briefly looked at them and updated them in a way that looks
superficially reasonable, but some of the uses will probably want to be
refined later.
2022-05-10 19:51:13 +01:00

72 lines
2.3 KiB
Plaintext

/**
* @name Useless upcast
* @description Upcasting a derived type to its base type is usually unnecessary.
* @kind problem
* @problem.severity warning
* @precision low
* @id java/useless-upcast
* @tags maintainability
* language-features
* external/cwe/cwe-561
*/
import java
predicate usefulUpcast(CastingExpr e) {
// Upcasts that may be performed to affect resolution of methods or constructors.
exists(Call c, int i, Callable target |
c.getArgument(i) = e and
target = c.getCallee() and
// An upcast to the type of the corresponding parameter.
e.getType() = target.getParameterType(i)
|
// There is an overloaded method/constructor in the class that we might be trying to avoid.
exists(Callable other |
other.getName() = target.getName() and
other.getSourceDeclaration() != target.getSourceDeclaration()
|
c.(MethodAccess).getReceiverType().inherits(other.(Method)) or
other = target.(Constructor).getDeclaringType().getAConstructor()
)
)
or
// Upcasts of a varargs argument.
exists(Call c, int iArg, int iParam | c.getArgument(iArg) = e |
c.getCallee().getParameter(iParam).isVarargs() and iArg >= iParam
)
or
// Upcasts that are performed on an operand of a ternary expression.
e = any(ConditionalExpr ce).getABranchExpr()
or
// Upcasts to raw types.
e.getType() instanceof RawType
or
e.getType().(Array).getElementType() instanceof RawType
or
// Upcasts that are performed to affect field, private method, or static method resolution.
exists(FieldAccess fa | e = fa.getQualifier() |
not e.getExpr().getType().(RefType).inherits(fa.getField())
)
or
exists(MethodAccess ma, Method m |
e = ma.getQualifier() and
m = ma.getMethod() and
(m.isStatic() or m.isPrivate())
|
not e.getExpr().getType().(RefType).inherits(m)
)
}
from Expr e, RefType src, RefType dest
where
exists(CastingExpr cse | cse = e |
(cse instanceof CastExpr or cse instanceof SafeCastExpr) and
exists(cse.getLocation()) and
src = cse.getExpr().getType() and
dest = cse.getType()
) and
dest = src.getAStrictAncestor() and
not usefulUpcast(e)
select e, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", src,
src.getName(), dest, dest.getName()