Skip to content

Commit ff45387

Browse files
committed
Java: Minor TypeFlow precision improvement and refactor.
1 parent d2f8029 commit ff45387

File tree

1 file changed

+55
-33
lines changed

1 file changed

+55
-33
lines changed

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

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,14 @@ private predicate joinStep0(TypeFlowNode n1, TypeFlowNode n2) {
7676
or
7777
n2.asExpr().(ConditionalExpr).getFalseExpr() = n1.asExpr()
7878
or
79-
n2.asField().getAnAssignedValue() = n1.asExpr()
79+
exists(Field f, Expr e |
80+
f = n2.asField() and
81+
f.getAnAssignedValue() = e and
82+
e = n1.asExpr() and
83+
not e.(FieldAccess).getField() = f
84+
)
8085
or
81-
n2.asSsa().(BaseSsaPhiNode).getAPhiInput() = n1.asSsa()
86+
n2.asSsa().(BaseSsaPhiNode).getAnUltimateLocalDefinition() = n1.asSsa()
8287
or
8388
exists(ReturnStmt ret |
8489
n2.asMethod() = ret.getEnclosingCallable() and ret.getResult() = n1.asExpr()
@@ -89,7 +94,9 @@ private predicate joinStep0(TypeFlowNode n1, TypeFlowNode n2) {
8994
exists(Argument arg, Parameter p |
9095
privateParamArg(p, arg) and
9196
n1.asExpr() = arg and
92-
n2.asSsa().(BaseSsaImplicitInit).isParameterDefinition(p)
97+
n2.asSsa().(BaseSsaImplicitInit).isParameterDefinition(p) and
98+
// skip trivial recursion
99+
not arg = n2.asSsa().getAUse()
93100
)
94101
}
95102

@@ -121,9 +128,18 @@ private predicate step(TypeFlowNode n1, TypeFlowNode n2) {
121128
private predicate isNull(TypeFlowNode n) {
122129
n.asExpr() instanceof NullLiteral
123130
or
131+
exists(LocalVariableDeclExpr decl |
132+
n.asSsa().(BaseSsaUpdate).getDefiningExpr() = decl and
133+
not decl.hasImplicitInit() and
134+
not exists(decl.getInit())
135+
)
136+
or
124137
exists(TypeFlowNode mid | isNull(mid) and step(mid, n))
125138
or
126-
forex(TypeFlowNode mid | joinStep0(mid, n) | isNull(mid))
139+
forex(TypeFlowNode mid | joinStep0(mid, n) | isNull(mid)) and
140+
// Fields that are never assigned a non-null value are probably set by
141+
// reflection and are thus not always null.
142+
not exists(n.asField())
127143
}
128144

129145
/**
@@ -155,6 +171,15 @@ private predicate joinStepRank(int r, TypeFlowNode n1, TypeFlowNode n2) {
155171

156172
private int lastRank(TypeFlowNode n) { result = max(int r | joinStepRank(r, _, n)) }
157173

174+
private predicate exactTypeBase(TypeFlowNode n, RefType t) {
175+
exists(ClassInstanceExpr e |
176+
n.asExpr() = e and
177+
e.getType() = t and
178+
not e instanceof FunctionalExpr and
179+
exists(RefType sub | sub.getASourceSupertype() = t.getSourceDeclaration())
180+
)
181+
}
182+
158183
private predicate exactTypeRank(int r, TypeFlowNode n, RefType t) {
159184
forall(TypeFlowNode mid | joinStepRank(r, mid, n) | exactType(mid, t)) and
160185
joinStepRank(r, _, n)
@@ -171,12 +196,7 @@ private predicate exactTypeJoin(int r, TypeFlowNode n, RefType t) {
171196
* non-trivial lower bound, that is, `t` has a subtype.
172197
*/
173198
private predicate exactType(TypeFlowNode n, RefType t) {
174-
exists(ClassInstanceExpr e |
175-
n.asExpr() = e and
176-
e.getType() = t and
177-
not e instanceof FunctionalExpr and
178-
exists(RefType sub | sub.getASourceSupertype() = t.getSourceDeclaration())
179-
)
199+
exactTypeBase(n, t)
180200
or
181201
exists(TypeFlowNode mid | exactType(mid, t) and step(mid, n))
182202
or
@@ -289,6 +309,24 @@ private predicate instanceOfGuarded(VarAccess va, RefType t) {
289309
)
290310
}
291311

312+
/**
313+
* Holds if `n` has type `t` and this information is discarded, such that `t`
314+
* might be a better type bound for nodes where `n` flows to.
315+
*/
316+
private predicate typeFlowBase(TypeFlowNode n, RefType t) {
317+
exists(RefType srctype |
318+
upcast(n, srctype) or
319+
upcastEnhancedForStmt(n.asSsa(), srctype) or
320+
downcastSuccessor(n.asExpr(), srctype) or
321+
instanceOfGuarded(n.asExpr(), srctype) or
322+
n.asExpr().(FunctionalExpr).getConstructedType() = srctype
323+
|
324+
t = srctype.(BoundedType).getAnUltimateUpperBoundType()
325+
or
326+
t = srctype and not srctype instanceof BoundedType
327+
)
328+
}
329+
292330
/**
293331
* Holds if `t` is a bound that holds on one of the incoming edges to `n` and
294332
* thus is a candidate bound for `n`.
@@ -320,15 +358,7 @@ private predicate typeFlowJoin(int r, TypeFlowNode n, RefType t) {
320358
* likely to be better than the static type of `n`.
321359
*/
322360
private predicate typeFlow(TypeFlowNode n, RefType t) {
323-
upcast(n, t)
324-
or
325-
upcastEnhancedForStmt(n.asSsa(), t)
326-
or
327-
downcastSuccessor(n.asExpr(), t)
328-
or
329-
instanceOfGuarded(n.asExpr(), t)
330-
or
331-
n.asExpr().(FunctionalExpr).getConstructedType() = t
361+
typeFlowBase(n, t)
332362
or
333363
exists(TypeFlowNode mid | typeFlow(mid, t) and step(mid, n))
334364
or
@@ -363,17 +393,13 @@ private module TypeFlowBounds {
363393
*/
364394
cached
365395
predicate fieldTypeFlow(Field f, RefType t, boolean exact) {
366-
exists(TypeFlowNode n, RefType srctype |
396+
exists(TypeFlowNode n |
367397
n.asField() = f and
368398
(
369-
exactType(n, srctype) and exact = true
399+
exactType(n, t) and exact = true
370400
or
371-
not exactType(n, _) and bestTypeFlow(n, srctype) and exact = false
401+
not exactType(n, _) and bestTypeFlow(n, t) and exact = false
372402
)
373-
|
374-
t = srctype.(BoundedType).getAnUltimateUpperBoundType()
375-
or
376-
t = srctype and not srctype instanceof BoundedType
377403
)
378404
}
379405

@@ -384,17 +410,13 @@ private module TypeFlowBounds {
384410
*/
385411
cached
386412
predicate exprTypeFlow(Expr e, RefType t, boolean exact) {
387-
exists(TypeFlowNode n, RefType srctype |
413+
exists(TypeFlowNode n |
388414
n.asExpr() = e and
389415
(
390-
exactType(n, srctype) and exact = true
416+
exactType(n, t) and exact = true
391417
or
392-
not exactType(n, _) and bestTypeFlow(n, srctype) and exact = false
418+
not exactType(n, _) and bestTypeFlow(n, t) and exact = false
393419
)
394-
|
395-
t = srctype.(BoundedType).getAnUltimateUpperBoundType()
396-
or
397-
t = srctype and not srctype instanceof BoundedType
398420
)
399421
}
400422
}

0 commit comments

Comments
 (0)