|
| 1 | +/** |
| 2 | + * Provides predicates for proving data flow properties that hold for all |
| 3 | + * paths, that is, reachability is computed using universal quantification over |
| 4 | + * the step relation. |
| 5 | + * |
| 6 | + * Regular data flow search for the existence of a path, that is, reachability |
| 7 | + * using existential quantification over the step relation. Hence, this library |
| 8 | + * computes the dual reachability predicate that states that a certain property |
| 9 | + * always holds for a given node regardless of the path taken. |
| 10 | + * |
| 11 | + * As a simple comparison, the computed predicate is essentially equivalent to |
| 12 | + * the folllowing: |
| 13 | + * ```ql |
| 14 | + * predicate hasProperty(FlowNode n, Prop t) { |
| 15 | + * basecase(n, t) |
| 16 | + * or |
| 17 | + * forex(FlowNode mid | step(mid, n) | hasProperty(mid, t)) |
| 18 | + * } |
| 19 | + * ``` |
| 20 | + * More complex property propagation is supported, and strongly connected |
| 21 | + * components in the flow graph are handled. |
| 22 | + * |
| 23 | + * As an initial such property calculation, the library computes the set of |
| 24 | + * nodes that are always null. These are then subtracted from the graph such |
| 25 | + * that subsequently calculated properties hold under the assumption that the |
| 26 | + * value is not null. |
| 27 | + */ |
| 28 | + |
1 | 29 | private import codeql.util.Location
|
2 | 30 | private import codeql.util.Unit
|
3 | 31 |
|
@@ -59,13 +87,21 @@ module UfMake<LocationSig Location, UniversalFlowInput<Location> I> {
|
59 | 87 | )
|
60 | 88 | }
|
61 | 89 |
|
62 |
| - /** |
63 |
| - * Holds if data can flow from `n1` to `n2` in one step, `n1` is not necessarily |
64 |
| - * functionally determined by `n2`, and `n1` might take a non-null value. |
65 |
| - */ |
66 |
| - predicate joinStepNotNull(FlowNode n1, FlowNode n2) { joinStep(n1, n2) and not isNull(n1) } |
| 90 | + private import Internal |
67 | 91 |
|
68 |
| - predicate anyStep(FlowNode n1, FlowNode n2) { joinStepNotNull(n1, n2) or uniqStep(n1, n2) } |
| 92 | + module Internal { |
| 93 | + /** |
| 94 | + * Holds if data can flow from `n1` to `n2` in one step, `n1` is not necessarily |
| 95 | + * functionally determined by `n2`, and `n1` might take a non-null value. |
| 96 | + */ |
| 97 | + predicate joinStepNotNull(FlowNode n1, FlowNode n2) { joinStep(n1, n2) and not isNull(n1) } |
| 98 | + |
| 99 | + /** |
| 100 | + * Holds if data can flow from `n1` to `n2` in one step, excluding join |
| 101 | + * steps from nodes that are always null. |
| 102 | + */ |
| 103 | + predicate anyStep(FlowNode n1, FlowNode n2) { joinStepNotNull(n1, n2) or uniqStep(n1, n2) } |
| 104 | + } |
69 | 105 |
|
70 | 106 | private predicate sccEdge(FlowNode n1, FlowNode n2) { anyStep(n1, n2) and anyStep+(n2, n1) }
|
71 | 107 |
|
|
0 commit comments