Skip to content

Commit bc57d87

Browse files
committed
Java: Address comments.
1 parent 784eef3 commit bc57d87

File tree

1 file changed

+64
-48
lines changed

1 file changed

+64
-48
lines changed

java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -158,16 +158,16 @@ private predicate joinStep(TypeFlowNode n1, TypeFlowNode n2) {
158158

159159
private predicate anyStep(TypeFlowNode n1, TypeFlowNode n2) { joinStep(n1, n2) or step(n1, n2) }
160160

161-
private predicate sccEdge(TypeFlowNode n1, TypeFlowNode n2) { anyStep(n1, n2) and anyStep+(n2, n1) }
161+
private import SccReduction
162162

163-
/*
163+
/**
164164
* SCC reduction.
165165
*
166166
* This ought to be as easy as `equivalenceRelation(sccEdge/2)(n, scc)`, but
167167
* this HOP is not currently supported for newtypes.
168168
*
169169
* A straightforward implementation would be:
170-
* ```
170+
* ```ql
171171
* predicate sccRepr(TypeFlowNode n, TypeFlowNode scc) {
172172
* scc =
173173
* max(TypeFlowNode n2 |
@@ -182,60 +182,67 @@ private predicate sccEdge(TypeFlowNode n1, TypeFlowNode n2) { anyStep(n1, n2) an
182182
* ```
183183
* but this is quadratic in the size of the SCCs.
184184
*
185-
* Instead we find local maxima and determine the SCC representatives from those.
185+
* Instead we find local maxima by following SCC edges and determine the SCC
186+
* representatives from those.
186187
* (This is still worst-case quadratic in the size of the SCCs, but generally
187188
* performs better.)
188189
*/
190+
private module SccReduction {
191+
private predicate sccEdge(TypeFlowNode n1, TypeFlowNode n2) {
192+
anyStep(n1, n2) and anyStep+(n2, n1)
193+
}
189194

190-
private predicate sccEdgeWithMax(TypeFlowNode n1, TypeFlowNode n2, TypeFlowNode m) {
191-
sccEdge(n1, n2) and
192-
m =
193-
max(TypeFlowNode n |
194-
n = [n1, n2]
195-
|
196-
n order by n.getLocation().getStartLine(), n.getLocation().getStartColumn(), getNodeKind(n)
197-
)
198-
}
195+
private predicate sccEdgeWithMax(TypeFlowNode n1, TypeFlowNode n2, TypeFlowNode m) {
196+
sccEdge(n1, n2) and
197+
m =
198+
max(TypeFlowNode n |
199+
n = [n1, n2]
200+
|
201+
n order by n.getLocation().getStartLine(), n.getLocation().getStartColumn(), getNodeKind(n)
202+
)
203+
}
199204

200-
private predicate hasLargerNeighbor(TypeFlowNode n) {
201-
exists(TypeFlowNode n2 |
202-
sccEdgeWithMax(n, n2, n2) and
203-
not sccEdgeWithMax(n, n2, n)
204-
or
205-
sccEdgeWithMax(n2, n, n2) and
206-
not sccEdgeWithMax(n2, n, n)
207-
)
208-
}
205+
private predicate hasLargerNeighbor(TypeFlowNode n) {
206+
exists(TypeFlowNode n2 |
207+
sccEdgeWithMax(n, n2, n2) and
208+
not sccEdgeWithMax(n, n2, n)
209+
or
210+
sccEdgeWithMax(n2, n, n2) and
211+
not sccEdgeWithMax(n2, n, n)
212+
)
213+
}
209214

210-
private predicate localMax(TypeFlowNode m) {
211-
sccEdgeWithMax(_, _, m) and
212-
not hasLargerNeighbor(m)
213-
}
215+
private predicate localMax(TypeFlowNode m) {
216+
sccEdgeWithMax(_, _, m) and
217+
not hasLargerNeighbor(m)
218+
}
214219

215-
private predicate sccReprFromLocalMax(TypeFlowNode scc) {
216-
exists(TypeFlowNode m |
217-
localMax(m) and
218-
scc =
219-
max(TypeFlowNode n2 |
220-
sccEdge+(m, n2) and localMax(n2)
221-
|
222-
n2
223-
order by
224-
n2.getLocation().getStartLine(), n2.getLocation().getStartColumn(), getNodeKind(n2)
225-
)
226-
)
227-
}
220+
private predicate sccReprFromLocalMax(TypeFlowNode scc) {
221+
exists(TypeFlowNode m |
222+
localMax(m) and
223+
scc =
224+
max(TypeFlowNode n2 |
225+
sccEdge+(m, n2) and localMax(n2)
226+
|
227+
n2
228+
order by
229+
n2.getLocation().getStartLine(), n2.getLocation().getStartColumn(), getNodeKind(n2)
230+
)
231+
)
232+
}
228233

229-
private predicate sccRepr(TypeFlowNode n, TypeFlowNode scc) {
230-
sccEdge+(n, scc) and sccReprFromLocalMax(scc)
231-
}
234+
/** Holds if `n` is part of an SCC of size 2 or more represented by `scc`. */
235+
predicate sccRepr(TypeFlowNode n, TypeFlowNode scc) {
236+
sccEdge+(n, scc) and sccReprFromLocalMax(scc)
237+
}
232238

233-
private predicate sccJoinStep(TypeFlowNode n, TypeFlowNode scc) {
234-
exists(TypeFlowNode mid |
235-
joinStep(n, mid) and
236-
sccRepr(mid, scc) and
237-
not sccRepr(n, scc)
238-
)
239+
predicate sccJoinStep(TypeFlowNode n, TypeFlowNode scc) {
240+
exists(TypeFlowNode mid |
241+
joinStep(n, mid) and
242+
sccRepr(mid, scc) and
243+
not sccRepr(n, scc)
244+
)
245+
}
239246
}
240247

241248
private signature predicate edgeSig(TypeFlowNode n1, TypeFlowNode n2);
@@ -247,6 +254,10 @@ private signature module RankedEdge {
247254
}
248255

249256
private module RankEdge<edgeSig/2 edge> implements RankedEdge {
257+
/**
258+
* Holds if `r` is a ranking of the incoming edges `(n1,n2)` to `n2`. The used
259+
* ordering is not necessarily total, so the ranking may have gaps.
260+
*/
250261
private predicate edgeRank1(int r, TypeFlowNode n1, TypeFlowNode n2) {
251262
n1 =
252263
rank[r](TypeFlowNode n |
@@ -256,10 +267,15 @@ private module RankEdge<edgeSig/2 edge> implements RankedEdge {
256267
)
257268
}
258269

270+
/**
271+
* Holds if `r2` is a ranking of the ranks from `edgeRank1`. This removes the
272+
* gaps from the ranking.
273+
*/
259274
private predicate edgeRank2(int r2, int r1, TypeFlowNode n) {
260275
r1 = rank[r2](int r | edgeRank1(r, _, n) | r)
261276
}
262277

278+
/** Holds if `r` is a ranking of the incoming edges `(n1,n2)` to `n2`. */
263279
predicate edgeRank(int r, TypeFlowNode n1, TypeFlowNode n2) {
264280
exists(int r1 |
265281
edgeRank1(r1, n1, n2) and

0 commit comments

Comments
 (0)