|
4 | 4 | * Provides an implementation of a fast initial pruning of global |
5 | 5 | * (interprocedural) data flow reachability (Stage 1). |
6 | 6 | */ |
7 | | -overlay[local?] |
| 7 | +overlay[local?] // when this is removed, put `overlay[local?]` on `isOverlayNode`. |
8 | 8 | module; |
9 | 9 |
|
10 | 10 | private import codeql.util.Unit |
@@ -129,23 +129,75 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> { |
129 | 129 |
|
130 | 130 | private module AlertFiltering = AlertFilteringImpl<Location>; |
131 | 131 |
|
| 132 | + /** |
| 133 | + * Holds if the given node is visible in overlay-only local evaluation. |
| 134 | + * |
| 135 | + * This predicate needs to be `overlay[local?]`, either directly or |
| 136 | + * through annotations from an outer scope. If `Node` is global for the |
| 137 | + * language under analysis, then every node is considered an overlay |
| 138 | + * node, which means there will effectively be no overlay-based |
| 139 | + * filtering of sources and sinks. |
| 140 | + */ |
| 141 | + private predicate isOverlayNode(Node node) { |
| 142 | + isEvaluatingInOverlay() and |
| 143 | + // Any local node is an overlay node if we are evaluating in overlay mode |
| 144 | + exists(node) |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * The filtering if we aren't meant to be diff-informed. |
| 149 | + * |
| 150 | + * Shared between sources and sinks. |
| 151 | + */ |
| 152 | + pragma[inline] |
| 153 | + private predicate nonDiffInformedFilter(Node node) { |
| 154 | + // If we are in base-only global evaluation, do not filter out any sources. |
| 155 | + not isEvaluatingInOverlay() |
| 156 | + or |
| 157 | + // If the configuration doesn't merge overlays, do not filter out any sources. |
| 158 | + not Config::observeOverlayInformedIncrementalMode() |
| 159 | + or |
| 160 | + // If we are in global evaluation with an overlay present, restrict |
| 161 | + // sources to those visible in the overlay. |
| 162 | + isOverlayNode(node) |
| 163 | + } |
| 164 | + |
| 165 | + overlay[global] |
132 | 166 | pragma[nomagic] |
133 | 167 | private predicate isFilteredSource(Node source) { |
134 | 168 | Config::isSource(source, _) and |
| 169 | + // Data flow is always incremental in one of two ways. |
| 170 | + // 1. If the configuration is diff-informed, we filter to only include nodes in the diff, |
| 171 | + // which gives the smallest set of nodes. |
| 172 | + // If diff information is not available, we do not filter at all. |
| 173 | + // 2. If not, in global evaluation with overlay, we filter to only |
| 174 | + // include nodes from files in the overlay; flow from |
| 175 | + // other nodes will be added back later. |
| 176 | + // We start by seeing if we should be in case 1. |
135 | 177 | if Config::observeDiffInformedIncrementalMode() |
136 | | - then AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source)) |
137 | | - else any() |
| 178 | + then |
| 179 | + // Case 1: We are meant to be diff-informed. |
| 180 | + // We still only filter if we have diff information. |
| 181 | + AlertFiltering::diffInformationAvailable() |
| 182 | + implies |
| 183 | + AlertFiltering::locationIsInDiff(Config::getASelectedSourceLocation(source)) |
| 184 | + else nonDiffInformedFilter(source) |
138 | 185 | } |
139 | 186 |
|
| 187 | + overlay[global] |
140 | 188 | pragma[nomagic] |
141 | 189 | private predicate isFilteredSink(Node sink) { |
142 | 190 | ( |
143 | 191 | Config::isSink(sink, _) or |
144 | 192 | Config::isSink(sink) |
145 | 193 | ) and |
| 194 | + // See the comments in `isFilteredSource` for the reasoning behind the following. |
146 | 195 | if Config::observeDiffInformedIncrementalMode() |
147 | | - then AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink)) |
148 | | - else any() |
| 196 | + then |
| 197 | + AlertFiltering::diffInformationAvailable() |
| 198 | + implies |
| 199 | + AlertFiltering::locationIsInDiff(Config::getASelectedSinkLocation(sink)) |
| 200 | + else nonDiffInformedFilter(sink) |
149 | 201 | } |
150 | 202 |
|
151 | 203 | private predicate hasFilteredSource() { isFilteredSource(_) } |
|
0 commit comments