Skip to content

Commit 5fed6c7

Browse files
committed
Java: Include two more base cases in TypeFlow to improve virtual dispatch.
1 parent 58285c0 commit 5fed6c7

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed

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

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -186,35 +186,39 @@ private predicate exactType(TypeFlowNode n, RefType t) {
186186
}
187187

188188
/**
189-
* Holds if `e` occurs in a position where type information might be discarded;
190-
* `t` is the potentially boxed type of `e`, `t1` is the erasure of `t`, and
189+
* Holds if `n` occurs in a position where type information might be discarded;
190+
* `t` is the potentially boxed type of `n`, `t1` is the erasure of `t`, and
191191
* `t2` is the erased type of the implicit or explicit cast.
192192
*/
193193
pragma[noinline]
194-
private predicate upcastCand(Expr e, RefType t, RefType t1, RefType t2) {
195-
t = boxIfNeeded(e.getType()) and
194+
private predicate upcastCand(TypeFlowNode n, RefType t, RefType t1, RefType t2) {
195+
t = boxIfNeeded(n.getType()) and
196196
t.getErasure() = t1 and
197197
(
198-
exists(Variable v | v.getAnAssignedValue() = e and t2 = v.getType().getErasure())
198+
exists(Variable v | v.getAnAssignedValue() = n.asExpr() and t2 = v.getType().getErasure())
199199
or
200-
exists(CastExpr c | c.getExpr() = e and t2 = c.getType().getErasure())
200+
exists(CastExpr c | c.getExpr() = n.asExpr() and t2 = c.getType().getErasure())
201201
or
202202
exists(ReturnStmt ret |
203-
ret.getResult() = e and t2 = ret.getEnclosingCallable().getReturnType().getErasure()
203+
ret.getResult() = n.asExpr() and t2 = ret.getEnclosingCallable().getReturnType().getErasure()
204204
)
205205
or
206-
exists(Parameter p | privateParamArg(p, e) and t2 = p.getType().getErasure())
206+
exists(MethodAccess ma | viableImpl_v1(ma) = n.asMethod() and t2 = ma.getType())
207207
or
208-
exists(ConditionalExpr cond | cond.getTrueExpr() = e or cond.getFalseExpr() = e |
208+
exists(Parameter p | privateParamArg(p, n.asExpr()) and t2 = p.getType().getErasure())
209+
or
210+
exists(ConditionalExpr cond |
211+
cond.getTrueExpr() = n.asExpr() or cond.getFalseExpr() = n.asExpr()
212+
|
209213
t2 = cond.getType().getErasure()
210214
)
211215
)
212216
}
213217

214-
/** Holds if `e` occurs in a position where type information is discarded. */
215-
private predicate upcast(Expr e, RefType t) {
218+
/** Holds if `n` occurs in a position where type information is discarded. */
219+
private predicate upcast(TypeFlowNode n, RefType t) {
216220
exists(RefType t1, RefType t2 |
217-
upcastCand(e, t, t1, t2) and
221+
upcastCand(n, t, t1, t2) and
218222
t1.getASourceSupertype+() = t2
219223
)
220224
}
@@ -316,14 +320,16 @@ private predicate typeFlowJoin(int r, TypeFlowNode n, RefType t) {
316320
* likely to be better than the static type of `n`.
317321
*/
318322
private predicate typeFlow(TypeFlowNode n, RefType t) {
319-
upcast(n.asExpr(), t)
323+
upcast(n, t)
320324
or
321325
upcastEnhancedForStmt(n.asSsa(), t)
322326
or
323327
downcastSuccessor(n.asExpr(), t)
324328
or
325329
instanceOfGuarded(n.asExpr(), t)
326330
or
331+
n.asExpr().(FunctionalExpr).getConstructedType() = t
332+
or
327333
exists(TypeFlowNode mid | typeFlow(mid, t) and step(mid, n))
328334
or
329335
typeFlowJoin(lastRank(n), n, t)

0 commit comments

Comments
 (0)