Skip to content

Commit fc8b439

Browse files
authored
Merge pull request github#6740 from aschackmull/java/callback-dispatch
Java: Add callback dispatch to more anonymous classes.
2 parents c294b75 + 4841c30 commit fc8b439

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -326,18 +326,24 @@ class LambdaCallKind = Method; // the "apply" method in the functional interface
326326

327327
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
328328
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
329-
exists(FunctionalExpr func, FunctionalInterface interface |
329+
exists(ClassInstanceExpr func, Interface t, FunctionalInterface interface |
330330
creation.asExpr() = func and
331-
func.asMethod() = c and
332-
func.getType().(RefType).getSourceDeclaration() = interface and
333-
kind = interface.getRunMethod()
331+
func.getAnonymousClass().getAMethod() = c and
332+
func.getConstructedType().extendsOrImplements+(t) and
333+
t.getSourceDeclaration() = interface and
334+
c.(Method).overridesOrInstantiates+(pragma[only_bind_into](kind)) and
335+
pragma[only_bind_into](kind) = interface.getRunMethod().getSourceDeclaration()
334336
)
335337
}
336338

337339
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
338340
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
339341
receiver = call.(SummaryCall).getReceiver() and
340-
getNodeDataFlowType(receiver).getSourceDeclaration().(FunctionalInterface).getRunMethod() = kind
342+
getNodeDataFlowType(receiver)
343+
.getSourceDeclaration()
344+
.(FunctionalInterface)
345+
.getRunMethod()
346+
.getSourceDeclaration() = kind
341347
}
342348

343349
/** Extra data-flow steps needed for lambda flow analysis. */

java/ql/test/library-tests/dataflow/callback-dispatch/A.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ static <T1,T2> T2 applyConverter1(T1 x, Converter1<T1,T2> con) {
4848
return null;
4949
}
5050

51+
public interface Producer1Consumer3<E> extends Producer1<E[]>, Consumer3<E[]> { }
52+
5153
static Object source(int i) { return null; }
5254

5355
static void sink(Object o) { }
@@ -71,7 +73,7 @@ void foo(boolean b1, boolean b2) {
7173

7274
applyConsumer1(source(4), new Consumer1() {
7375
@Override public void eat(Object o) {
74-
sink(o); // $ MISSING: flow=4
76+
sink(o); // $ flow=4
7577
}
7678
});
7779

@@ -96,5 +98,16 @@ void foo2() {
9698
sink(applyConverter1((Integer)source(9), i -> i)); // $ flow=9
9799

98100
sink(applyConverter1((Integer)source(10), i -> new int[]{i})[0]); // $ flow=10
101+
102+
Producer1Consumer3<Integer> pc = new Producer1Consumer3<Integer>() {
103+
@Override public Integer[] make() {
104+
return new Integer[] { (Integer)source(11) };
105+
}
106+
@Override public void eat(Integer[] xs) {
107+
sink(xs[0]); // $ flow=12
108+
}
109+
};
110+
applyConsumer3(new Integer[] { (Integer)source(12) }, pc);
111+
sink(applyProducer1(pc)[0]); // $ flow=11
99112
}
100113
}

0 commit comments

Comments
 (0)