From b9b9394259ff394462c4ee32a6e1eb70f056576d Mon Sep 17 00:00:00 2001 From: Chuan-kai Lin Date: Tue, 28 Jan 2025 07:51:45 -0800 Subject: [PATCH 1/2] AlertFiltering: allow multiple filtering predicates This commit rephrases the documentation for the restrictAlertsTo predicate and renames the predicate columns for clarity. The new documentation should be equivalent to the old documentation, except allowing for the possibility that there may be multiple alert filtering predicates. --- shared/util/codeql/util/AlertFiltering.qll | 41 +++++++++++++--------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/shared/util/codeql/util/AlertFiltering.qll b/shared/util/codeql/util/AlertFiltering.qll index 6ca62e50af22..e7c01807e6f7 100644 --- a/shared/util/codeql/util/AlertFiltering.qll +++ b/shared/util/codeql/util/AlertFiltering.qll @@ -6,22 +6,31 @@ private import codeql.util.Location /** - * Restricts alerts to a specific location in specific files. + * Holds if the query should produce alerts that match the given line ranges. * - * If this predicate is empty, accept all alerts. Otherwise, accept alerts only at the specified - * locations. Note that alert restrictions apply only to the start line of an alert (even if the - * alert location spans multiple lines) because alerts are displayed on their start lines. + * This predicate is active if and only if it is nonempty. If this predicate is inactive, it has no + * effect. If it is active, it accepts any alert that has at least one matching location. * - * - filePath: Absolute path of the file to restrict alerts to. - * - startLine: Start line number (starting with 1, inclusive) to restrict alerts to. - * - endLine: End line number (starting with 1, inclusive) to restrict alerts to. + * Note that an alert that is not accepted by this filtering predicate may still be included in the + * query results if it is accepted by another active filtering predicate in this module. An alert is + * excluded from the query results if only if (1) there is at least one active filtering predicate, + * and (2) it is not accepted by any active filtering predicate. * - * If startLine and endLine are both 0, accept alerts anywhere in the file. + * An alert location is a match if it matches a row in this predicate. If `startLineStart` and + * `startLineEnd` are both 0, the row specifies a whole-file match, and a location is a match if + * its file path matches `filePath`. Otherwise, the row specifies a line-range match, and a + * location is a match if its file path matches `filePath`, and its start line is between + * `startLineStart` and `startLineEnd`, inclusive. (Note that only start line of the location is + * used for matching because an alert is displayed on the first line of its location.) * - * A query should either completely ignore this predicate (i.e., perform no filtering whatsoever), - * or only return alerts that meet the filtering criteria as specified above. + * - filePath: alert location file path (absolute). + * - startLineStart: inclusive start of the range for alert location start line number (1-based). + * - startLineEnd: inclusive end of the range for alert location start line number (1-based). + * + * A query should either perform no alert filtering, or adhere to all the filtering rules in this + * module and return all and only the accepted alerts. */ -extensible predicate restrictAlertsTo(string filePath, int startLine, int endLine); +extensible predicate restrictAlertsTo(string filePath, int startLineStart, int startLineEnd); /** Module for applying alert location filtering. */ module AlertFilteringImpl { @@ -30,14 +39,14 @@ module AlertFilteringImpl { predicate filterByLocation(Location location) { not restrictAlertsTo(_, _, _) or - exists(string filePath, int startLine, int endLine | - restrictAlertsTo(filePath, startLine, endLine) + exists(string filePath, int startLineStart, int startLineEnd | + restrictAlertsTo(filePath, startLineStart, startLineEnd) | - startLine = 0 and - endLine = 0 and + startLineStart = 0 and + startLineEnd = 0 and location.hasLocationInfo(filePath, _, _, _, _) or - location.hasLocationInfo(filePath, [startLine .. endLine], _, _, _) + location.hasLocationInfo(filePath, [startLineStart .. startLineEnd], _, _, _) ) } } From 96caa686fc1f4a1b6d8841e1062f5f6a89fb840d Mon Sep 17 00:00:00 2001 From: Chuan-kai Lin Date: Wed, 29 Jan 2025 07:50:45 -0800 Subject: [PATCH 2/2] AlertFiltering: add restrictAlertsToExactLocation This commit introduces a new extensible predicate restrictAlertsToExactLocation, which is similar to the existing restrictAlertsTo predicate but matches alert locations exactly. --- shared/util/codeql/util/AlertFiltering.qll | 47 +++++++++++++++++++++- shared/util/ext/default-alert-filter.yml | 6 +++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/shared/util/codeql/util/AlertFiltering.qll b/shared/util/codeql/util/AlertFiltering.qll index e7c01807e6f7..97acd803f01e 100644 --- a/shared/util/codeql/util/AlertFiltering.qll +++ b/shared/util/codeql/util/AlertFiltering.qll @@ -29,15 +29,54 @@ private import codeql.util.Location * * A query should either perform no alert filtering, or adhere to all the filtering rules in this * module and return all and only the accepted alerts. + * + * This predicate is suitable for situations where we want to filter alerts at line granularity, + * such as based on the pull request diff. + * + * See also: `restrictAlertsToExactLocation`. */ extensible predicate restrictAlertsTo(string filePath, int startLineStart, int startLineEnd); +/** + * Holds if the query should produce alerts that match the given locations. + * + * This predicate is active if and only if it is nonempty. If this predicate is inactive, it has no + * effect. If it is active, it accepts any alert that has at least one matching location. + * + * Note that an alert that is not accepted by this filtering predicate may still be included in the + * query results if it is accepted by another active filtering predicate in this module. An alert is + * excluded from the query results if only if (1) there is at least one active filtering predicate, + * and (2) it is not accepted by any active filtering predicate. + * + * An alert location is a match if it matches a row in this predicate. Each row specifies an exact + * location: an alert location is a match if its file path matches `filePath`, its start line and + * column match `startLine` and `startColumn`, and its end line and column match `endLine` and + * `endColumn`. + * + * - filePath: alert location file path (absolute). + * - startLine: alert location start line number (1-based). + * - startColumn: alert location start column number (1-based). + * - endLine: alert location end line number (1-based). + * - endColumn: alert location end column number (1-based). + * + * A query should either perform no alert filtering, or adhere to all the filtering rules in this + * module and return all and only the accepted alerts. + * + * This predicate is suitable for situations where we want to filter by the exact alert location, + * distinguishing between alerts on the same line. + * + * See also: `restrictAlertsTo`. + */ +extensible predicate restrictAlertsToExactLocation( + string filePath, int startLine, int startColumn, int endLine, int endColumn +); + /** Module for applying alert location filtering. */ module AlertFilteringImpl { /** Applies alert filtering to the given location. */ bindingset[location] predicate filterByLocation(Location location) { - not restrictAlertsTo(_, _, _) + not restrictAlertsTo(_, _, _) and not restrictAlertsToExactLocation(_, _, _, _, _) or exists(string filePath, int startLineStart, int startLineEnd | restrictAlertsTo(filePath, startLineStart, startLineEnd) @@ -48,5 +87,11 @@ module AlertFilteringImpl { or location.hasLocationInfo(filePath, [startLineStart .. startLineEnd], _, _, _) ) + or + exists(string filePath, int startLine, int startColumn, int endLine, int endColumn | + restrictAlertsToExactLocation(filePath, startLine, startColumn, endLine, endColumn) + | + location.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn) + ) } } diff --git a/shared/util/ext/default-alert-filter.yml b/shared/util/ext/default-alert-filter.yml index 0ae5a2f4eb5b..1c4dd263d055 100644 --- a/shared/util/ext/default-alert-filter.yml +++ b/shared/util/ext/default-alert-filter.yml @@ -5,3 +5,9 @@ extensions: extensible: restrictAlertsTo # Empty predicate means no restrictions on alert locations data: [] + + - addsTo: + pack: codeql/util + extensible: restrictAlertsToExactLocation + # Empty predicate means no restrictions on alert locations + data: []