@@ -60,6 +60,9 @@ signature module UniversalFlowInput<LocationSig Location> {
60
60
default predicate isExcludedFromNullAnalysis ( FlowNode n ) { none ( ) }
61
61
}
62
62
63
+ /**
64
+ * Provides an implementation of universal flow using input `I`.
65
+ */
63
66
module Make< LocationSig Location, UniversalFlowInput< Location > I> {
64
67
private import I
65
68
@@ -93,6 +96,7 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
93
96
94
97
private import Internal
95
98
99
+ /** Provides access to internal step relations. */
96
100
module Internal {
97
101
/**
98
102
* Holds if data can flow from `n1` to `n2` in one step, `n1` is not necessarily
@@ -242,6 +246,10 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
242
246
default predicate barrier ( FlowNode n ) { none ( ) }
243
247
}
244
248
249
+ /**
250
+ * Calculates a (nullary) property using universal flow given a base case
251
+ * relation.
252
+ */
245
253
module FlowNullary< NullaryPropertySig P> {
246
254
private module Propagation implements PropPropagation {
247
255
class Prop = Unit ;
@@ -251,6 +259,10 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
251
259
predicate supportsProp = candProp / 2 ;
252
260
}
253
261
262
+ /**
263
+ * Holds if all flow reaching `n` originates from nodes in
264
+ * `hasPropertyBase`.
265
+ */
254
266
predicate hasProperty ( FlowNode n ) {
255
267
P:: hasPropertyBase ( n )
256
268
or
@@ -283,6 +295,10 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
283
295
default predicate barrier ( FlowNode n ) { none ( ) }
284
296
}
285
297
298
+ /**
299
+ * Calculates a unary property using universal flow given a base case
300
+ * relation.
301
+ */
286
302
module Flow< PropertySig P> {
287
303
private module Propagation implements PropPropagation {
288
304
class Prop = P:: Prop ;
@@ -296,8 +312,9 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
296
312
}
297
313
298
314
/**
299
- * Holds if the runtime type of `n` is exactly `t` and if this bound is a
300
- * non-trivial lower bound, that is, `t` has a subtype.
315
+ * Holds if all flow reaching `n` originates from nodes in
316
+ * `hasPropertyBase`. The property `t` is taken from one of those origins
317
+ * such that all other origins imply `t`.
301
318
*/
302
319
predicate hasProperty ( FlowNode n , P:: Prop t ) {
303
320
P:: hasPropertyBase ( n , t )
@@ -307,13 +324,25 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
307
324
exists ( FlowNode mid | hasProperty ( mid , t ) and uniqStepNotNull ( mid , n ) )
308
325
or
309
326
// The following is an optimized version of
310
- // `forex(FlowNode mid | joinStepNotNull(mid, n) | hasPropery(mid, t))`
327
+ // ```
328
+ // exists(FlowNode mid | joinStepNotNull(mid, n) | hasPropery(mid, t)) and
329
+ // forall(FlowNode mid | joinStepNotNull(mid, n) | hasPropery(mid, _)) and
330
+ // forall(FlowNode mid, P::Prop t0 | joinStepNotNull(mid, n) and hasPropery(mid, t0) |
331
+ // P::propImplies(t0, t)
332
+ // )
333
+ // ```
311
334
ForAll< FlowNode , RankedJoinStep , Propagation > :: flowJoin ( n , t )
312
335
or
313
336
exists ( FlowScc scc |
314
337
sccRepr ( n , scc ) and
315
338
// Optimized version of
316
- // `forex(FlowNode mid | sccJoinStepNotNull(mid, scc) | hasPropery(mid, t))`
339
+ // ```
340
+ // exists(FlowNode mid | sccJoinStepNotNull(mid, n) | hasPropery(mid, t)) and
341
+ // forall(FlowNode mid | sccJoinStepNotNull(mid, n) | hasPropery(mid, _)) and
342
+ // forall(FlowNode mid, P::Prop t0 | sccJoinStepNotNull(mid, n) and hasPropery(mid, t0) |
343
+ // P::propImplies(t0, t)
344
+ // )
345
+ // ```
317
346
ForAll< FlowScc , RankedSccJoinStep , Propagation > :: flowJoin ( scc , t )
318
347
)
319
348
)
0 commit comments