github / github/codeql

Java: `RefType.getAnAncestor()` is error-prone when supertype is parameterized type with Object as type argument

Abierto
#5,595 2 comentarios 0 reacciones 0 asignados Ver en GitHub
Java question
Lenguaje dominante
CodeQL
Estrellas
10.1k
Forks
2.1k
Merge medio
2 d 15 h
PR fusionados (30 d)
141

Descripción

The predicate [`RefType.getAnAcestor()`](https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Type.qll/predicate.Type$RefType$getAnAncestor.0.html) is error-prone when one of the supertypes is a generic type parameterized with `Object` as type argument. In that case `getASupertype()` and `getAnAcestor()` return all types which have a lower bound (but are not actually relevant), e.g.:
```ql
import java

from RefType t
where t.hasName("ObjectToStringComparator")
select t, t.getAnAncestor()
```
[Query Console link](https://lgtm.com/query/7884599397805363842/)

Result hierarchy (click to expand)

- `ObjectToStringComparator`
- `Serializable`
- `Object`
- `Comparator`
- `Comparator<>`
- `Comparator`
- `Comparator>`
- `Comparator`
- `Comparator>`
- `Comparator>`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator>`
- `Comparator>`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator>`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator>>`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Comparator`
- `Object`

This is most likely not the desired behavior. Therefore it might be good to deprecate `getAnAncestor()` and instead add a predicate `getASourceAncestor()` (which also deliberately does not have `this` as result):
```ql
/**
* Gets a source ancestor of this type, that is, a direct supertype or a direct supertype of the
* source declaration of a supertype, recursively.
*/
RefType getASourceAncestor() {
// Checking for source declaration is necessary, otherwise class `Generic` would have `Generic<>` (raw),
// `Generic` and `Generic` as supertypes
result = getASupertype() and result.getSourceDeclaration() != getSourceDeclaration()
or result = getASourceAncestor(getASupertype().getSourceDeclaration())
}
```

As seen here, it is necessary to check `result.getSourceDeclaration() != getSourceDeclaration()` since `RefType` is currently missing a predicate for getting a supertype declared in source (or the implicit `Object`); this is slightly related to #3818.
Ideally such a predicate would have the name `getASourceSupertype()`, however that name is already [taken](https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Type.qll/predicate.Type$RefType$getASourceSupertype.0.html). A better fitting name for the existing predicate would probably be `getASupertypeSource()` / `getASupertypeSourceDeclaration()`, since that is what it actually does: "Gets the source declaration of a direct supertype of this type"

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.