Skip to content

Commit acd4cf2

Browse files
authored
Merge pull request github#5636 from aschackmull/java/shared-flow-summaries
Java: Adopt shared flow summaries
2 parents e8d835b + fd8f745 commit acd4cf2

File tree

10 files changed

+1285
-364
lines changed

10 files changed

+1285
-364
lines changed

config/identical-files.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
5757
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll"
5858
],
59+
"DataFlow Java/C# Flow Summaries": [
60+
"java/ql/src/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
61+
"csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll"
62+
],
5963
"SsaReadPosition Java/C#": [
6064
"java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
6165
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Provides classes and predicates for definining flow summaries.
3+
*/
4+
5+
import java
6+
private import internal.FlowSummaryImpl as Impl
7+
private import internal.DataFlowDispatch
8+
private import internal.DataFlowPrivate
9+
10+
// import all instances below
11+
private module Summaries { }
12+
13+
class SummaryComponent = Impl::Public::SummaryComponent;
14+
15+
/** Provides predicates for constructing summary components. */
16+
module SummaryComponent {
17+
import Impl::Public::SummaryComponent
18+
19+
/** Gets a summary component that represents a qualifier. */
20+
SummaryComponent qualifier() { result = argument(-1) }
21+
22+
/** Gets a summary component for field `f`. */
23+
SummaryComponent field(Field f) { result = content(any(FieldContent c | c.getField() = f)) }
24+
25+
/** Gets a summary component that represents the return value of a call. */
26+
SummaryComponent return() { result = return(_) }
27+
}
28+
29+
class SummaryComponentStack = Impl::Public::SummaryComponentStack;
30+
31+
/** Provides predicates for constructing stacks of summary components. */
32+
module SummaryComponentStack {
33+
import Impl::Public::SummaryComponentStack
34+
35+
/** Gets a singleton stack representing a qualifier. */
36+
SummaryComponentStack qualifier() { result = singleton(SummaryComponent::qualifier()) }
37+
38+
/** Gets a stack representing a field `f` of `object`. */
39+
SummaryComponentStack fieldOf(Field f, SummaryComponentStack object) {
40+
result = push(SummaryComponent::field(f), object)
41+
}
42+
43+
/** Gets a singleton stack representing a (normal) return. */
44+
SummaryComponentStack return() { result = singleton(SummaryComponent::return()) }
45+
}
46+
47+
class SummarizedCallable = Impl::Public::SummarizedCallable;
48+
49+
class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack;

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@ private import java
22
private import DataFlowPrivate
33
private import DataFlowUtil
44
private import semmle.code.java.dataflow.InstanceAccess
5-
import semmle.code.java.dispatch.VirtualDispatch
5+
private import semmle.code.java.dataflow.FlowSummary
6+
private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch
67

78
private module DispatchImpl {
9+
/** Gets a viable implementation of the target of the given `Call`. */
10+
Callable viableCallable(Call c) {
11+
result = VirtualDispatch::viableCallable(c)
12+
or
13+
result.(SummarizedCallable) = c.getCallee().getSourceDeclaration()
14+
}
15+
816
/**
917
* Holds if the set of viable implementations that can be called by `ma`
1018
* might be improved by knowing the call context. This is the case if the
1119
* qualifier is the `i`th parameter of the enclosing callable `c`.
1220
*/
1321
private predicate mayBenefitFromCallContext(MethodAccess ma, Callable c, int i) {
1422
exists(Parameter p |
15-
2 <= strictcount(viableImpl(ma)) and
23+
2 <= strictcount(VirtualDispatch::viableImpl(ma)) and
1624
ma.getQualifier().(VarAccess).getVariable() = p and
1725
p.getPosition() = i and
1826
c.getAParameter() = p and
@@ -21,7 +29,7 @@ private module DispatchImpl {
2129
)
2230
or
2331
exists(OwnInstanceAccess ia |
24-
2 <= strictcount(viableImpl(ma)) and
32+
2 <= strictcount(VirtualDispatch::viableImpl(ma)) and
2533
(ia.isExplicit(ma.getQualifier()) or ia.isImplicitMethodQualifier(ma)) and
2634
i = -1 and
2735
c = ma.getEnclosingCallable()
@@ -60,7 +68,7 @@ private module DispatchImpl {
6068
or
6169
ctx.getArgument(i) = arg
6270
|
63-
src = variableTrack(arg) and
71+
src = VirtualDispatch::variableTrack(arg) and
6472
srctype = getPreciseType(src) and
6573
if src instanceof ClassInstanceExpr then exact = true else exact = false
6674
)
@@ -93,18 +101,18 @@ private module DispatchImpl {
93101
* restricted to those `ma`s for which a context might make a difference.
94102
*/
95103
Method viableImplInCallContext(MethodAccess ma, Call ctx) {
96-
result = viableImpl(ma) and
104+
result = VirtualDispatch::viableImpl(ma) and
97105
exists(int i, Callable c, Method def, RefType t, boolean exact |
98106
mayBenefitFromCallContext(ma, c, i) and
99107
c = viableCallable(ctx) and
100108
contextArgHasType(ctx, i, t, exact) and
101109
ma.getMethod() = def
102110
|
103-
exact = true and result = exactMethodImpl(def, t.getSourceDeclaration())
111+
exact = true and result = VirtualDispatch::exactMethodImpl(def, t.getSourceDeclaration())
104112
or
105113
exact = false and
106114
exists(RefType t2 |
107-
result = viableMethodImpl(def, t.getSourceDeclaration(), t2) and
115+
result = VirtualDispatch::viableMethodImpl(def, t.getSourceDeclaration(), t2) and
108116
not failsUnification(t, t2)
109117
)
110118
)
@@ -117,7 +125,7 @@ private module DispatchImpl {
117125

118126
pragma[noinline]
119127
private predicate unificationTargetRight(ParameterizedType t2, GenericType g) {
120-
exists(viableMethodImpl(_, _, t2)) and t2.getGenericType() = g
128+
exists(VirtualDispatch::viableMethodImpl(_, _, t2)) and t2.getGenericType() = g
121129
}
122130

123131
private predicate unificationTargets(Type t1, Type t2) {

0 commit comments

Comments
 (0)