Skip to content

Commit b454101

Browse files
committed
Shared: Make UniversalFlow overlay-aware.
1 parent 607ad1f commit b454101

File tree

6 files changed

+113
-29
lines changed

6 files changed

+113
-29
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TypeFlow.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ private module Input implements TypeFlowInput<Location> {
206206

207207
predicate isNullValue(TypeFlowNode n) { n.isNullValue() }
208208

209+
overlay[local]
210+
predicate isEvaluatingInOverlay() { none() }
211+
209212
private newtype TType =
210213
TSingle() or
211214
TBuffer()

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ private RefType boxIfNeeded(J::Type t) {
2525

2626
/** Provides the input types and predicates for instantiation of `UniversalFlow`. */
2727
module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
28+
overlay[local]
2829
private newtype TFlowNode =
2930
TField(Field f) { not f.getType() instanceof PrimitiveType } or
3031
TSsa(Base::SsaDefinition ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or
@@ -34,6 +35,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
3435
/**
3536
* A `Field`, `BaseSsaVariable`, `Expr`, or `Method`.
3637
*/
38+
overlay[local]
3739
class FlowNode extends TFlowNode {
3840
/** Gets a textual representation of this element. */
3941
string toString() {
@@ -158,6 +160,11 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
158160
// reflection and are thus not always null.
159161
exists(n.asField())
160162
}
163+
164+
private import semmle.code.java.Overlay as Overlay
165+
166+
overlay[local]
167+
predicate isEvaluatingInOverlay() { Overlay::isOverlay() }
161168
}
162169

163170
private module Input implements TypeFlowInput<Location> {

java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -129,31 +129,35 @@ private predicate safeCallable(Callable c) {
129129
c.hasQualifiedName("org.apache.commons.lang3", "StringUtils", "join")
130130
}
131131

132+
overlay[local]
133+
private predicate collectionWithPossibleMutationBase(FlowNode n) {
134+
not unmodifiableCollection(n) and
135+
exists(Expr e |
136+
n.asExpr() = e and
137+
(e.getType() instanceof CollectionType or e.getType() instanceof Array) and
138+
not collectionAddition(_, e, _) and
139+
not collectionStep(n, _)
140+
|
141+
exists(ArrayAccess aa | e = aa.getArray())
142+
or
143+
exists(Call c, Callable tgt | c.getAnArgument() = e or c.getQualifier() = e |
144+
tgt = c.getCallee().getSourceDeclaration() and
145+
not safeCallable(tgt)
146+
)
147+
)
148+
}
149+
132150
/**
133151
* Holds if `n` might be mutated in ways that adds elements that are not
134152
* tracked by the `collectionAddition` predicate.
135153
*/
136154
private predicate collectionWithPossibleMutation(FlowNode n) {
155+
collectionWithPossibleMutationBase(n)
156+
or
137157
not unmodifiableCollection(n) and
138-
(
139-
exists(Expr e |
140-
n.asExpr() = e and
141-
(e.getType() instanceof CollectionType or e.getType() instanceof Array) and
142-
not collectionAddition(_, e, _) and
143-
not collectionStep(n, _)
144-
|
145-
exists(ArrayAccess aa | e = aa.getArray())
146-
or
147-
exists(Call c, Callable tgt | c.getAnArgument() = e or c.getQualifier() = e |
148-
tgt = c.getCallee().getSourceDeclaration() and
149-
not safeCallable(tgt)
150-
)
151-
)
152-
or
153-
exists(FlowNode mid |
154-
FlowStepsInput::step(n, mid) and
155-
collectionWithPossibleMutation(mid)
156-
)
158+
exists(FlowNode mid |
159+
FlowStepsInput::step(n, mid) and
160+
collectionWithPossibleMutation(mid)
157161
)
158162
}
159163

shared/typeflow/codeql/typeflow/TypeFlow.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ signature module TypeFlowInput<LocationSig Location> {
4545
*/
4646
default predicate isExcludedFromNullAnalysis(TypeFlowNode n) { none() }
4747

48+
/**
49+
* Holds if the evaluator is currently evaluating with an overlay. The
50+
* implementation of this predicate needs to be `overlay[local]`. For a
51+
* language with no overlay support, `none()` is a valid implementation.
52+
*
53+
* When called from a local predicate, this predicate holds if we are in the
54+
* overlay-only local evaluation. When called from a global predicate, this
55+
* predicate holds if we are evaluating globally with overlay and base both
56+
* visible.
57+
*/
58+
predicate isEvaluatingInOverlay();
59+
4860
/** A type. */
4961
class Type {
5062
/** Gets a textual representation of this type. */

shared/typeflow/codeql/typeflow/UniversalFlow.qll

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ signature module UniversalFlowInput<LocationSig Location> {
6060
* the null analysis determines that `n` is always null.
6161
*/
6262
default predicate isExcludedFromNullAnalysis(FlowNode n) { none() }
63+
64+
/**
65+
* Holds if the evaluator is currently evaluating with an overlay. The
66+
* implementation of this predicate needs to be `overlay[local]`. For a
67+
* language with no overlay support, `none()` is a valid implementation.
68+
*
69+
* When called from a local predicate, this predicate holds if we are in the
70+
* overlay-only local evaluation. When called from a global predicate, this
71+
* predicate holds if we are evaluating globally with overlay and base both
72+
* visible.
73+
*/
74+
predicate isEvaluatingInOverlay();
6375
}
6476

6577
/**
@@ -68,23 +80,46 @@ signature module UniversalFlowInput<LocationSig Location> {
6880
module Make<LocationSig Location, UniversalFlowInput<Location> I> {
6981
private import I
7082

83+
overlay[local?]
84+
private predicate overlayNode(FlowNode n) { isEvaluatingInOverlay() and exists(n) }
85+
86+
overlay[global]
87+
private predicate canReachOverlay(FlowNode n) {
88+
overlayNode(n)
89+
or
90+
exists(FlowNode mid | canReachOverlay(mid) and step(n, mid))
91+
}
92+
93+
bindingset[n]
94+
private predicate relevantNode(FlowNode n) {
95+
not isEvaluatingInOverlay()
96+
or
97+
canReachOverlay(n)
98+
}
99+
71100
/**
72101
* Holds if data can flow from `n1` to `n2` in one step, and `n1` is
73102
* functionally determined by `n2`.
74103
*/
75-
private predicate uniqStep(FlowNode n1, FlowNode n2) { n1 = unique(FlowNode n | step(n, n2)) }
104+
private predicate uniqStep(FlowNode n1, FlowNode n2) {
105+
n1 = unique(FlowNode n | step(n, n2)) and relevantNode(n2)
106+
}
76107

77108
/**
78109
* Holds if data can flow from `n1` to `n2` in one step, and `n1` is not
79110
* functionally determined by `n2`.
80111
*/
81-
private predicate joinStep(FlowNode n1, FlowNode n2) { step(n1, n2) and not uniqStep(n1, n2) }
112+
private predicate joinStep(FlowNode n1, FlowNode n2) {
113+
step(n1, n2) and not uniqStep(n1, n2) and relevantNode(n2)
114+
}
82115

83116
/** Holds if `null` is the only value that flows to `n`. */
84117
private predicate isNull(FlowNode n) {
85-
isNullValue(n)
118+
isNullValue(n) and
119+
relevantNode(n)
86120
or
87121
not isExcludedFromNullAnalysis(n) and
122+
relevantNode(n) and
88123
(
89124
exists(FlowNode mid | isNull(mid) and uniqStep(mid, n))
90125
or
@@ -256,21 +291,24 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
256291
private module Propagation implements PropPropagation {
257292
class Prop = Unit;
258293

259-
predicate candProp(FlowNode n, Unit u) { hasProperty(n) and exists(u) }
294+
predicate candProp(FlowNode n, Unit u) { hasPropertyImpl(n) and exists(u) }
260295

261296
predicate supportsProp = candProp/2;
262297
}
263298

264299
/**
265300
* Holds if all flow reaching `n` originates from nodes in
266301
* `hasPropertyBase`.
302+
*
303+
* When evaluated in an overlay-merged context, this is restricted to nodes
304+
* that can reach the overlay.
267305
*/
268-
predicate hasProperty(FlowNode n) {
306+
private predicate hasPropertyImpl(FlowNode n) {
269307
P::hasPropertyBase(n)
270308
or
271309
not P::barrier(n) and
272310
(
273-
exists(FlowNode mid | hasProperty(mid) and uniqStepNotNull(mid, n))
311+
exists(FlowNode mid | hasPropertyImpl(mid) and uniqStepNotNull(mid, n))
274312
or
275313
// The following is an optimized version of
276314
// `forex(FlowNode mid | joinStepNotNull(mid, n) | hasPropery(mid))`
@@ -284,6 +322,13 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
284322
)
285323
)
286324
}
325+
326+
/**
327+
* Holds if all flow reaching `n` originates from nodes in
328+
* `hasPropertyBase`.
329+
*/
330+
overlay[local?]
331+
predicate hasProperty(FlowNode n) = forceLocal(hasPropertyImpl/1)(n)
287332
}
288333

289334
signature module PropertySig {
@@ -305,25 +350,28 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
305350
private module Propagation implements PropPropagation {
306351
class Prop = P::Prop;
307352

308-
predicate candProp = hasProperty/2;
353+
predicate candProp = hasPropertyImpl/2;
309354

310355
bindingset[t]
311356
predicate supportsProp(FlowNode n, Prop t) {
312-
exists(Prop t0 | hasProperty(n, t0) and P::propImplies(t0, t))
357+
exists(Prop t0 | hasPropertyImpl(n, t0) and P::propImplies(t0, t))
313358
}
314359
}
315360

316361
/**
317362
* Holds if all flow reaching `n` originates from nodes in
318363
* `hasPropertyBase`. The property `t` is taken from one of those origins
319364
* such that all other origins imply `t`.
365+
*
366+
* When evaluated in an overlay-merged context, this is restricted to nodes
367+
* that can reach the overlay.
320368
*/
321-
predicate hasProperty(FlowNode n, P::Prop t) {
369+
private predicate hasPropertyImpl(FlowNode n, P::Prop t) {
322370
P::hasPropertyBase(n, t)
323371
or
324372
not P::barrier(n) and
325373
(
326-
exists(FlowNode mid | hasProperty(mid, t) and uniqStepNotNull(mid, n))
374+
exists(FlowNode mid | hasPropertyImpl(mid, t) and uniqStepNotNull(mid, n))
327375
or
328376
// The following is an optimized version of
329377
// ```
@@ -349,5 +397,13 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
349397
)
350398
)
351399
}
400+
401+
/**
402+
* Holds if all flow reaching `n` originates from nodes in
403+
* `hasPropertyBase`. The property `t` is taken from one of those origins
404+
* such that all other origins imply `t`.
405+
*/
406+
overlay[local?]
407+
predicate hasProperty(FlowNode n, P::Prop t) = forceLocal(hasPropertyImpl/2)(n, t)
352408
}
353409
}

shared/typeflow/codeql/typeflow/internal/TypeFlowImpl.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ module TypeFlow<LocationSig Location, TypeFlowInput<Location> I> {
1717
predicate isNullValue = I::isNullValue/1;
1818

1919
predicate isExcludedFromNullAnalysis = I::isExcludedFromNullAnalysis/1;
20+
21+
predicate isEvaluatingInOverlay = I::isEvaluatingInOverlay/0;
2022
}
2123

2224
private module UnivFlow = UniversalFlow::Make<Location, UfInput>;

0 commit comments

Comments
 (0)