Skip to content

Commit 311e62f

Browse files
authored
Merge pull request #4081 from aschackmull/java/dispatch-ctx-this-param
Approved by aibaars
2 parents caa680c + bcad18f commit 311e62f

4 files changed

Lines changed: 127 additions & 11 deletions

File tree

java/ql/src/semmle/code/java/dataflow/internal/DataFlowDispatch.qll

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
private import java
22
private import DataFlowPrivate
3+
private import DataFlowUtil
4+
private import semmle.code.java.dataflow.InstanceAccess
35
import semmle.code.java.dispatch.VirtualDispatch
46

57
private module DispatchImpl {
@@ -17,6 +19,13 @@ private module DispatchImpl {
1719
not p.isVarargs() and
1820
c = ma.getEnclosingCallable()
1921
)
22+
or
23+
exists(OwnInstanceAccess ia |
24+
2 <= strictcount(viableImpl(ma)) and
25+
(ia.isExplicit(ma.getQualifier()) or ia.isImplicitMethodQualifier(ma)) and
26+
i = -1 and
27+
c = ma.getEnclosingCallable()
28+
)
2029
}
2130

2231
/**
@@ -37,18 +46,32 @@ private module DispatchImpl {
3746
* relevant call context.
3847
*/
3948
private predicate contextArgHasType(Call ctx, int i, RefType t, boolean exact) {
40-
exists(Expr arg, Expr src |
41-
relevantContext(ctx, i) and
42-
ctx.getArgument(i) = arg and
43-
src = variableTrack(arg) and
44-
exists(RefType srctype | srctype = src.getType() |
45-
exists(TypeVariable v | v = srctype |
46-
t = v.getUpperBoundType+() and not t instanceof TypeVariable
47-
)
49+
relevantContext(ctx, i) and
50+
exists(RefType srctype |
51+
exists(Expr arg, Expr src |
52+
i = -1 and
53+
ctx.getQualifier() = arg
4854
or
49-
t = srctype and not srctype instanceof TypeVariable
50-
) and
51-
if src instanceof ClassInstanceExpr then exact = true else exact = false
55+
ctx.getArgument(i) = arg
56+
|
57+
src = variableTrack(arg) and
58+
srctype = src.getType() and
59+
if src instanceof ClassInstanceExpr then exact = true else exact = false
60+
)
61+
or
62+
exists(Node arg |
63+
i = -1 and
64+
not exists(ctx.getQualifier()) and
65+
getInstanceArgument(ctx) = arg and
66+
arg.getTypeBound() = srctype and
67+
if ctx instanceof ClassInstanceExpr then exact = true else exact = false
68+
)
69+
|
70+
exists(TypeVariable v | v = srctype |
71+
t = v.getUpperBoundType+() and not t instanceof TypeVariable
72+
)
73+
or
74+
t = srctype and not srctype instanceof TypeVariable
5275
)
5376
}
5477

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
public class A {
2+
static void sink(Object x) { }
3+
4+
static Object source() { return null; }
5+
6+
static class C1 {
7+
C1() { }
8+
9+
C1(Object x) {
10+
foo(x);
11+
}
12+
13+
void wrapFoo1(Object x) {
14+
foo(x);
15+
}
16+
17+
void wrapFoo2(Object x) {
18+
this.foo(x);
19+
}
20+
21+
void foo(Object x) {
22+
Object c1 = x;
23+
sink(c1);
24+
}
25+
}
26+
27+
static class C2 extends C1 {
28+
C2() { }
29+
30+
C2(Object x) {
31+
super(x);
32+
}
33+
34+
void foo(Object x) {
35+
Object c2 = x;
36+
sink(c2);
37+
}
38+
39+
void callWrapFoo2() {
40+
wrapFoo2(source());
41+
}
42+
}
43+
44+
static void wrapFoo3(C1 c1, Object x) {
45+
c1.foo(x);
46+
}
47+
48+
void test(C1 c) {
49+
c.wrapFoo1(source());
50+
c.wrapFoo2(source());
51+
wrapFoo3(c, source());
52+
53+
new C1(source());
54+
new C1().wrapFoo1(source());
55+
new C1().wrapFoo2(source());
56+
wrapFoo3(new C1(), source());
57+
58+
new C2(source());
59+
new C2().wrapFoo1(source());
60+
new C2().wrapFoo2(source());
61+
wrapFoo3(new C2(), source());
62+
}
63+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
| A.java:40:16:40:23 | source(...) | A.java:36:12:36:13 | c2 |
2+
| A.java:49:16:49:23 | source(...) | A.java:23:12:23:13 | c1 |
3+
| A.java:49:16:49:23 | source(...) | A.java:36:12:36:13 | c2 |
4+
| A.java:50:16:50:23 | source(...) | A.java:23:12:23:13 | c1 |
5+
| A.java:50:16:50:23 | source(...) | A.java:36:12:36:13 | c2 |
6+
| A.java:51:17:51:24 | source(...) | A.java:23:12:23:13 | c1 |
7+
| A.java:51:17:51:24 | source(...) | A.java:36:12:36:13 | c2 |
8+
| A.java:53:12:53:19 | source(...) | A.java:23:12:23:13 | c1 |
9+
| A.java:54:23:54:30 | source(...) | A.java:23:12:23:13 | c1 |
10+
| A.java:55:23:55:30 | source(...) | A.java:23:12:23:13 | c1 |
11+
| A.java:56:24:56:31 | source(...) | A.java:23:12:23:13 | c1 |
12+
| A.java:58:12:58:19 | source(...) | A.java:36:12:36:13 | c2 |
13+
| A.java:59:23:59:30 | source(...) | A.java:36:12:36:13 | c2 |
14+
| A.java:60:23:60:30 | source(...) | A.java:36:12:36:13 | c2 |
15+
| A.java:61:24:61:31 | source(...) | A.java:36:12:36:13 | c2 |
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import java
2+
import semmle.code.java.dataflow.DataFlow
3+
import DataFlow
4+
5+
class Conf extends Configuration {
6+
Conf() { this = "qqconf" }
7+
8+
override predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("source") }
9+
10+
override predicate isSink(Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") }
11+
}
12+
13+
from Node src, Node sink, Conf c
14+
where c.hasFlow(src, sink)
15+
select src, sink

0 commit comments

Comments
 (0)