mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
Java: Add callback dispatch to more anonymous classes.
This commit is contained in:
@@ -326,18 +326,24 @@ class LambdaCallKind = Method; // the "apply" method in the functional interface
|
||||
|
||||
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
|
||||
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
|
||||
exists(FunctionalExpr func, FunctionalInterface interface |
|
||||
exists(ClassInstanceExpr func, Interface t, FunctionalInterface interface |
|
||||
creation.asExpr() = func and
|
||||
func.asMethod() = c and
|
||||
func.getType().(RefType).getSourceDeclaration() = interface and
|
||||
kind = interface.getRunMethod()
|
||||
func.getAnonymousClass().getAMethod() = c and
|
||||
func.getConstructedType().extendsOrImplements+(t) and
|
||||
t.getSourceDeclaration() = interface and
|
||||
c.(Method).overridesOrInstantiates+(pragma[only_bind_into](kind)) and
|
||||
pragma[only_bind_into](kind) = interface.getRunMethod().getSourceDeclaration()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
receiver = call.(SummaryCall).getReceiver() and
|
||||
getNodeDataFlowType(receiver).getSourceDeclaration().(FunctionalInterface).getRunMethod() = kind
|
||||
getNodeDataFlowType(receiver)
|
||||
.getSourceDeclaration()
|
||||
.(FunctionalInterface)
|
||||
.getRunMethod()
|
||||
.getSourceDeclaration() = kind
|
||||
}
|
||||
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
|
||||
@@ -48,6 +48,8 @@ public class A {
|
||||
return null;
|
||||
}
|
||||
|
||||
public interface Producer1Consumer3<E> extends Producer1<E[]>, Consumer3<E[]> { }
|
||||
|
||||
static Object source(int i) { return null; }
|
||||
|
||||
static void sink(Object o) { }
|
||||
@@ -71,7 +73,7 @@ public class A {
|
||||
|
||||
applyConsumer1(source(4), new Consumer1() {
|
||||
@Override public void eat(Object o) {
|
||||
sink(o); // $ MISSING: flow=4
|
||||
sink(o); // $ flow=4
|
||||
}
|
||||
});
|
||||
|
||||
@@ -96,5 +98,16 @@ public class A {
|
||||
sink(applyConverter1((Integer)source(9), i -> i)); // $ flow=9
|
||||
|
||||
sink(applyConverter1((Integer)source(10), i -> new int[]{i})[0]); // $ flow=10
|
||||
|
||||
Producer1Consumer3<Integer> pc = new Producer1Consumer3<Integer>() {
|
||||
@Override public Integer[] make() {
|
||||
return new Integer[] { (Integer)source(11) };
|
||||
}
|
||||
@Override public void eat(Integer[] xs) {
|
||||
sink(xs[0]); // $ flow=12
|
||||
}
|
||||
};
|
||||
applyConsumer3(new Integer[] { (Integer)source(12) }, pc);
|
||||
sink(applyProducer1(pc)[0]); // $ flow=11
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user