Skip to content

Commit 2707be3

Browse files
committed
Java: Make virtual dispatch global while keeping ssa local.
1 parent 91ced7e commit 2707be3

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ private module Cached {
345345
* Constructor --(intraInstanceCallEdge)-->+ Method(setter of this.f)
346346
* ```
347347
*/
348+
overlay[global]
348349
private predicate intraInstanceCallEdge(Callable c1, Method m2) {
349350
exists(MethodCall ma, RefType t1 |
350351
ma.getCaller() = c1 and
@@ -365,6 +366,7 @@ private module Cached {
365366
)
366367
}
367368

369+
overlay[global]
368370
private Callable tgt(Call c) {
369371
result = viableImpl_v2(c)
370372
or
@@ -374,11 +376,13 @@ private module Cached {
374376
}
375377

376378
/** Holds if `(c1,c2)` is an edge in the call graph. */
379+
overlay[global]
377380
private predicate callEdge(Callable c1, Callable c2) {
378381
exists(Call c | c.getCaller() = c1 and c2 = tgt(c))
379382
}
380383

381384
/** Holds if `(c1,c2)` is an edge in the call graph excluding `intraInstanceCallEdge`. */
385+
overlay[global]
382386
private predicate crossInstanceCallEdge(Callable c1, Callable c2) {
383387
callEdge(c1, c2) and not intraInstanceCallEdge(c1, c2)
384388
}
@@ -392,6 +396,7 @@ private module Cached {
392396
relevantFieldUpdate(_, f.getField(), _)
393397
}
394398

399+
overlay[global]
395400
private predicate source(Call call, TrackedField f, Field field, Callable c, boolean fresh) {
396401
relevantCall(call, f) and
397402
field = f.getField() and
@@ -405,9 +410,11 @@ private module Cached {
405410
* `fresh` indicates whether the instance `this` in `c` has been freshly
406411
* allocated along the call-chain.
407412
*/
413+
overlay[global]
408414
private newtype TCallableNode =
409415
MkCallableNode(Callable c, boolean fresh) { source(_, _, _, c, fresh) or edge(_, c, fresh) }
410416

417+
overlay[global]
411418
private predicate edge(TCallableNode n, Callable c2, boolean f2) {
412419
exists(Callable c1, boolean f1 | n = MkCallableNode(c1, f1) |
413420
intraInstanceCallEdge(c1, c2) and f2 = f1
@@ -417,13 +424,15 @@ private module Cached {
417424
)
418425
}
419426

427+
overlay[global]
420428
private predicate edge(TCallableNode n1, TCallableNode n2) {
421429
exists(Callable c2, boolean f2 |
422430
edge(n1, c2, f2) and
423431
n2 = MkCallableNode(c2, f2)
424432
)
425433
}
426434

435+
overlay[global]
427436
pragma[noinline]
428437
private predicate source(Call call, TrackedField f, Field field, TCallableNode n) {
429438
exists(Callable c, boolean fresh |
@@ -432,52 +441,64 @@ private module Cached {
432441
)
433442
}
434443

444+
overlay[global]
435445
private predicate sink(Callable c, Field f, TCallableNode n) {
436446
setsOwnField(c, f) and n = MkCallableNode(c, false)
437447
or
438448
setsOtherField(c, f) and n = MkCallableNode(c, _)
439449
}
440450

451+
overlay[global]
441452
private predicate prunedNode(TCallableNode n) {
442453
sink(_, _, n)
443454
or
444455
exists(TCallableNode mid | edge(n, mid) and prunedNode(mid))
445456
}
446457

458+
overlay[global]
447459
private predicate prunedEdge(TCallableNode n1, TCallableNode n2) {
448460
prunedNode(n1) and
449461
prunedNode(n2) and
450462
edge(n1, n2)
451463
}
452464

465+
overlay[global]
453466
private predicate edgePlus(TCallableNode c1, TCallableNode c2) = fastTC(prunedEdge/2)(c1, c2)
454467

455468
/**
456469
* Holds if there exists a call-chain originating in `call` that can update `f` on some instance
457470
* where `f` and `call` share the same enclosing callable in which a
458471
* `FieldRead` of `f` is reachable from `call`.
459472
*/
473+
overlay[global]
460474
pragma[noopt]
461-
private predicate updatesNamedFieldImpl(Call call, TrackedField f, Callable setter) {
475+
private predicate updatesNamedFieldImplGlobal(Call call, TrackedField f, Callable setter) {
462476
exists(TCallableNode src, TCallableNode sink, Field field |
463477
source(call, f, field, src) and
464478
sink(setter, field, sink) and
465479
(src = sink or edgePlus(src, sink))
466480
)
467481
}
468482

483+
private predicate updatesNamedFieldImpl(Call call, TrackedField f, Callable setter) =
484+
forceLocal(updatesNamedFieldImplGlobal/3)(call, f, setter)
485+
469486
bindingset[call, f]
470487
pragma[inline_late]
471488
private predicate updatesNamedField0(Call call, TrackedField f, Callable setter) {
472489
updatesNamedField(call, f, setter)
473490
}
474491

475492
cached
476-
predicate defUpdatesNamedField(SsaImplicitUpdate def, TrackedField f, Callable setter) {
493+
predicate defUpdatesNamedFieldImpl(SsaImplicitUpdate def, TrackedField f, Callable setter) {
477494
f = def.getSourceVariable() and
478495
updatesNamedField0(def.getCfgNode().asCall(), f, setter)
479496
}
480497

498+
cached
499+
predicate defUpdatesNamedField(SsaImplicitUpdate def, TrackedField f, Callable setter) =
500+
forceLocal(defUpdatesNamedFieldImpl/3)(def, f, setter)
501+
481502
cached
482503
predicate ssaUncertainImplicitUpdate(SsaImplicitUpdate def) {
483504
exists(SsaSourceVariable v, BasicBlock bb, int i |

java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
* Provides predicates for reasoning about runtime call targets through virtual
33
* dispatch.
44
*/
5-
overlay[local?]
6-
module;
75

86
import java
97
import semmle.code.java.dataflow.TypeFlow

0 commit comments

Comments
 (0)