Skip to content

Commit ad461a8

Browse files
committed
Dataflow: Strengthen tracked types.
1 parent 1d87f07 commit ad461a8

File tree

2 files changed

+82
-23
lines changed

2 files changed

+82
-23
lines changed

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

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
11351135
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
11361136
);
11371137

1138-
bindingset[node, state, t, ap]
1139-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
1138+
bindingset[node, state, t0, ap]
1139+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
11401140

11411141
bindingset[typ, contentType]
11421142
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,9 +1199,20 @@ module Impl<FullStateConfigSig Config> {
11991199
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
12001200
ApOption argAp, Typ t, Ap ap, ApApprox apa
12011201
) {
1202-
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
1202+
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
1203+
}
1204+
1205+
private predicate fwdFlow1(
1206+
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
1207+
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
1208+
) {
1209+
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
12031210
PrevStage::revFlow(node, state, apa) and
1204-
filter(node, state, t, ap)
1211+
filter(node, state, t0, ap, t)
1212+
}
1213+
1214+
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
1215+
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
12051216
}
12061217

12071218
pragma[assume_small_delta]
@@ -1331,6 +1342,11 @@ module Impl<FullStateConfigSig Config> {
13311342
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
13321343
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
13331344
cons = apCons(c, t1, tail)
1345+
or
1346+
exists(Typ t0 |
1347+
typeStrengthen(t0, cons, t2) and
1348+
fwdFlowConsCand(t0, cons, c, t1, tail)
1349+
)
13341350
}
13351351

13361352
pragma[nomagic]
@@ -1955,10 +1971,10 @@ module Impl<FullStateConfigSig Config> {
19551971
)
19561972
}
19571973

1958-
bindingset[node, state, t, ap]
1959-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
1974+
bindingset[node, state, t0, ap]
1975+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
19601976
PrevStage::revFlowState(state) and
1961-
exists(t) and
1977+
t0 = t and
19621978
exists(ap) and
19631979
not stateBarrier(node, state) and
19641980
(
@@ -2210,10 +2226,16 @@ module Impl<FullStateConfigSig Config> {
22102226
)
22112227
}
22122228

2213-
bindingset[node, state, t, ap]
2214-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
2229+
bindingset[node, state, t0, ap]
2230+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
22152231
exists(state) and
2216-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
2232+
// We can get away with not using type strengthening here, since we aren't
2233+
// going to use the tracked types in the construction of Stage 4 access
2234+
// paths. For Stage 4 and onwards, the tracked types must be consistent as
2235+
// the cons candidates including types are used to construct subsequent
2236+
// access path approximations.
2237+
t0 = t and
2238+
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
22172239
(
22182240
notExpectsContent(node)
22192241
or
@@ -2325,11 +2347,18 @@ module Impl<FullStateConfigSig Config> {
23252347
)
23262348
}
23272349

2328-
bindingset[node, state, t, ap]
2329-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
2350+
bindingset[node, state, t0, ap]
2351+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
23302352
exists(state) and
23312353
not clear(node, ap) and
2332-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
2354+
(
2355+
if castingNodeEx(node)
2356+
then
2357+
exists(Typ nt | nt = node.getDataFlowType() |
2358+
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
2359+
)
2360+
else t = t0
2361+
) and
23332362
(
23342363
notExpectsContent(node)
23352364
or
@@ -2601,9 +2630,16 @@ module Impl<FullStateConfigSig Config> {
26012630
)
26022631
}
26032632

2604-
bindingset[node, state, t, ap]
2605-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
2606-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
2633+
bindingset[node, state, t0, ap]
2634+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
2635+
(
2636+
if castingNodeEx(node)
2637+
then
2638+
exists(Typ nt | nt = node.getDataFlowType() |
2639+
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
2640+
)
2641+
else t = t0
2642+
) and
26072643
exists(state) and
26082644
exists(ap)
26092645
}
@@ -2812,9 +2848,7 @@ module Impl<FullStateConfigSig Config> {
28122848
ap = TAccessPathNil()
28132849
or
28142850
// ... or a step from an existing PathNode to another node.
2815-
pathStep(_, node, state, cc, sc, t, ap) and
2816-
Stage5::revFlow(node, state, ap.getApprox()) and
2817-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
2851+
pathStep(_, node, state, cc, sc, t, ap)
28182852
} or
28192853
TPathNodeSink(NodeEx node, FlowState state) {
28202854
exists(PathNodeMid sink |
@@ -3332,13 +3366,31 @@ module Impl<FullStateConfigSig Config> {
33323366
ap = mid.getAp()
33333367
}
33343368

3369+
private predicate pathStep(
3370+
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
3371+
AccessPath ap
3372+
) {
3373+
exists(DataFlowType t0 |
3374+
pathStep0(mid, node, state, cc, sc, t0, ap) and
3375+
Stage5::revFlow(node, state, ap.getApprox()) and
3376+
(
3377+
if castingNodeEx(node)
3378+
then
3379+
exists(DataFlowType nt | nt = node.getDataFlowType() |
3380+
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
3381+
)
3382+
else t = t0
3383+
)
3384+
)
3385+
}
3386+
33353387
/**
33363388
* Holds if data may flow from `mid` to `node`. The last step in or out of
33373389
* a callable is recorded by `cc`.
33383390
*/
33393391
pragma[assume_small_delta]
33403392
pragma[nomagic]
3341-
private predicate pathStep(
3393+
private predicate pathStep0(
33423394
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
33433395
AccessPath ap
33443396
) {

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ predicate expectsContent(Node n, ContentSet c) {
176176
* possible flow. A single type is used for all numeric types to account for
177177
* numeric conversions, and otherwise the erasure is used.
178178
*/
179-
DataFlowType getErasedRepr(Type t) {
179+
RefType getErasedRepr(Type t) {
180180
exists(Type e | e = t.getErasure() |
181181
if e instanceof NumericOrCharType
182182
then result.(BoxedType).getPrimitiveType().getName() = "double"
@@ -189,6 +189,15 @@ DataFlowType getErasedRepr(Type t) {
189189
t instanceof NullType and result instanceof TypeObject
190190
}
191191

192+
class DataFlowType extends SrcRefType {
193+
DataFlowType() { this = getErasedRepr(_) }
194+
}
195+
196+
pragma[nomagic]
197+
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) {
198+
t1.getASourceSupertype+() = t2
199+
}
200+
192201
pragma[noinline]
193202
DataFlowType getNodeType(Node n) {
194203
result = getErasedRepr(n.getTypeBound())
@@ -259,8 +268,6 @@ class DataFlowCallable extends TDataFlowCallable {
259268

260269
class DataFlowExpr = Expr;
261270

262-
class DataFlowType = RefType;
263-
264271
private newtype TDataFlowCall =
265272
TCall(Call c) or
266273
TSummaryCall(SummarizedCallable c, Node receiver) {

0 commit comments

Comments
 (0)