mirror of
https://github.com/github/codeql.git
synced 2026-03-01 13:23:49 +01:00
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.
72 lines
2.3 KiB
Plaintext
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()
|