mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Java: Consider classes that has a method that returns an iterator as container like types.
This commit is contained in:
@@ -1,14 +1,38 @@
|
||||
private import java
|
||||
private import semmle.code.java.Collections
|
||||
private import semmle.code.java.dataflow.internal.ContainerFlow
|
||||
private import CaptureModelsSpecific as Specific
|
||||
private import CaptureModels
|
||||
|
||||
/**
|
||||
* TODO: We might just inline this instead.
|
||||
* Holds if `t` is a collection of type `tv` (eg. `List<T>`)
|
||||
* A type representing classes that has a method which returns an iterator.
|
||||
*/
|
||||
private predicate genericCollectionType(CollectionType t, TypeVariable tv) {
|
||||
t.getElementType() = tv
|
||||
private class IterableType extends Class {
|
||||
private Type elementType;
|
||||
|
||||
IterableType() {
|
||||
exists(Method m, Type return | m.getDeclaringType() = this |
|
||||
return = m.getReturnType() and
|
||||
return.getName().matches("Iterator%") and
|
||||
elementType = return.(ParameterizedType).getTypeArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the iterator element type of `this`.
|
||||
*/
|
||||
Type getElementType() { result = elementType }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `t` is a container like type of `tv` (eg. `List<T>`).
|
||||
*/
|
||||
private predicate genericContainerType(RefType t, TypeVariable tv) {
|
||||
(
|
||||
t.(ContainerType).getElementType() = tv
|
||||
or
|
||||
t.(IterableType).getElementType() = tv
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,8 +51,7 @@ private predicate localTypeParameter(Callable callable, TypeVariable tv) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `callable` has a type parameter `tv`
|
||||
* or collection parameterized over type `tv`.
|
||||
* Holds if `callable` has a type parameter `tv` or container parameterized over type `tv`.
|
||||
*/
|
||||
private predicate parameter(Callable callable, string input, TypeVariable tv) {
|
||||
exists(Parameter p |
|
||||
@@ -38,8 +61,8 @@ private predicate parameter(Callable callable, string input, TypeVariable tv) {
|
||||
// Parameter of type tv
|
||||
p.getType() = tv
|
||||
or
|
||||
// Parameter is a collection of type tv
|
||||
genericCollectionType(p.getType(), tv)
|
||||
// Parameter is a container of type tv
|
||||
genericContainerType(p.getType(), tv)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -58,7 +81,7 @@ private string getSyntheticField(TypeVariable tv) {
|
||||
private string implicit(Callable callable, TypeVariable tv) {
|
||||
classTypeParameter(callable, tv) and
|
||||
exists(string access |
|
||||
if genericCollectionType(callable.getDeclaringType(), tv)
|
||||
if genericContainerType(callable.getDeclaringType(), tv)
|
||||
then access = ".Element"
|
||||
else access = getSyntheticField(tv)
|
||||
|
|
||||
@@ -83,13 +106,13 @@ private class Function extends ParameterizedType {
|
||||
Type getParameterType() { result = this.getTypeArgument(0) }
|
||||
|
||||
/**
|
||||
* Get the return type of `this` function.
|
||||
* Gets the return type of `this` function.
|
||||
*/
|
||||
Type getReturnType() { result = this.getTypeArgument(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `callable` has a functional interface parameter `fi` at parameter position `position`.
|
||||
* Holds if `callable` has a function parameter `f` at parameter position `position`.
|
||||
*/
|
||||
private predicate functional(Callable callable, Function f, int position) {
|
||||
exists(Parameter p |
|
||||
@@ -110,9 +133,9 @@ bindingset[callable]
|
||||
private string getAccess(Callable callable, Type return, TypeVariable tv) {
|
||||
return = tv and result = ""
|
||||
or
|
||||
genericCollectionType(return, tv) and result = ".Element"
|
||||
genericContainerType(return, tv) and result = ".Element"
|
||||
or
|
||||
not genericCollectionType(return, tv) and
|
||||
not genericContainerType(return, tv) and
|
||||
(
|
||||
return.(ParameterizedType).getATypeArgument() = tv
|
||||
or
|
||||
@@ -123,7 +146,7 @@ private string getAccess(Callable callable, Type return, TypeVariable tv) {
|
||||
|
||||
/**
|
||||
* Holds if `input` is a models as data string representation of, how a value of type `tv`
|
||||
* (or a generic parameterized over `tv`) can be generated by a functionalinterface parameter of `callable`.
|
||||
* (or a generic parameterized over `tv`) can be generated by a function parameter of `callable`.
|
||||
*/
|
||||
private predicate functionalSource(Callable callable, string input, TypeVariable tv) {
|
||||
exists(Function f, int position, Type return, string access |
|
||||
@@ -141,7 +164,7 @@ private predicate functionalSource(Callable callable, string input, TypeVariable
|
||||
* This includes
|
||||
* (1) The implicit synthetic field(s) of the declaring type of `callable`.
|
||||
* (2) The parameters of `callable`.
|
||||
* (3) Any delegate parameters of `callable`.
|
||||
* (3) Any function parameters of `callable`.
|
||||
*/
|
||||
private predicate input(Callable callable, string input, TypeVariable tv) {
|
||||
input = implicit(callable, tv)
|
||||
@@ -163,9 +186,9 @@ private predicate returns(Callable callable, TypeVariable tv, string output) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `callable` has a functional interface parameter that accepts a value of type `tv`
|
||||
* Holds if `callable` has a function parameter that accepts a value of type `tv`
|
||||
* and `output` is the models as data string representation of, how data is routed to
|
||||
* the delegate parameter.
|
||||
* the function parameter.
|
||||
*/
|
||||
private predicate functionalSink(Callable callable, TypeVariable tv, string output) {
|
||||
exists(Function f, int position |
|
||||
@@ -181,7 +204,7 @@ private predicate functionalSink(Callable callable, TypeVariable tv, string outp
|
||||
* This includes
|
||||
* (1) The implicit synthetic field(s) of the declaring type of `callable`.
|
||||
* (2) The return of `callable`.
|
||||
* (3) Any delegate parameters of `callable`.
|
||||
* (3) Any function parameters of `callable`.
|
||||
*/
|
||||
private predicate output(Callable callable, TypeVariable tv, string output) {
|
||||
output = implicit(callable, tv)
|
||||
@@ -199,7 +222,6 @@ class TypeBasedFlowTargetApi extends Specific::TargetApiSpecific {
|
||||
TypeBasedFlowTargetApi() { Specific::isRelevantForTypeBasedFlowModels(this) }
|
||||
|
||||
/**
|
||||
* TODO: Update with Java examples instead.
|
||||
* Gets the string representation of all type based summaries for `this`
|
||||
* inspired by the Theorems for Free approach.
|
||||
*
|
||||
@@ -212,12 +234,12 @@ class TypeBasedFlowTargetApi extends Specific::TargetApiSpecific {
|
||||
* a (synthetic) field and return the result.
|
||||
* (4) `Apply<S1,S2>` is assumed to apply the provided function to provided value
|
||||
* and return the result.
|
||||
* ```csharp
|
||||
* ```java
|
||||
* public class MyGeneric<T> {
|
||||
* public void Set(T x) { ... }
|
||||
* public T Get() { ... }
|
||||
* public S Apply<S>(Func<T, S> f) { ... }
|
||||
* public S2 Apply<S1, S2>(S1 x, Func<S1, S2> f) { ... }
|
||||
* public void set(T x) { ... }
|
||||
* public T get() { ... }
|
||||
* public <S> S apply<S>(Function<T, S> f) { ... }
|
||||
* public <S1,S2> S2 apply<S1, S2>(S1 x, Function<S1, S2> f) { ... }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user