-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathAlertFiltering.qll
More file actions
123 lines (117 loc) · 5.9 KB
/
Copy pathAlertFiltering.qll
File metadata and controls
123 lines (117 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* Provides the `restrictAlertsTo` and `restrictAlertsToExactLocation` extensible predicate to
* restrict alerts to specific source locations, and the `AlertFilteringImpl` parameterized module
* to apply the filtering.
*/
overlay[local?]
module;
private import codeql.util.Location
/**
* Holds if the query may restrict its computation to only produce alerts that match the given line
* ranges. This predicate is used for implementing _diff-informed queries_ for pull requests in
* GitHub Code Scanning.
*
* This predicate is active if and only if it is nonempty. If this predicate is inactive, it has no
* effect. If it is active, queries may omit alerts that don't have a matching (see below) _primary_
* or _related_ location (in SARIF terminology). Queries are still allowed to produce alerts that
* have no matching locations, but they are not required to do so.
*
* An alert location is a match if it matches a row in this predicate. If `lineStart` and
* `lineEnd` 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 character range intersects
* with the range from the beginning of `lineStart` to the end of `lineEnd`.
*
* - filePath: alert location file path (absolute).
* - lineStart: inclusive start of the line range (1-based).
* - lineEnd: inclusive end of the line range (1-based).
*
* Note that even if an alert has no matching locations for this filtering predicate, it could still
* have matching locations for other filtering predicates in this module. In that case, queries must
* still produce such an alert. An alert can be omitted only if (1) there is at least one active
* filtering predicate, and (2) it has no matching locations for any active filtering predicate.
*
* See also: `restrictAlertsToExactLocation`.
*/
extensible predicate restrictAlertsTo(string filePath, int lineStart, int lineEnd);
/**
* Holds if the query may restrict its computation to only produce alerts that match the given
* character ranges. This predicate is suitable for testing, where we want to distinguish between
* alerts on the same line.
*
* This predicate is active if and only if it is nonempty. If this predicate is inactive, it has no
* effect. If it is active, queries may omit alerts that don't have a matching (see below) _primary_
* or _related_ location (in SARIF terminology). Queries are still allowed to produce alerts that
* have no matching locations, but they are not required to do so.
*
* An alert location is a match if it matches a row in this predicate. Each row specifies a
* character-range match, and a location is a match if its file path matches `filePath`, and its
* character range wholly contains the character range from `startColumn` on `startLine` to
* `endColumn` on `endLine` (inclusive).
*
* - filePath: alert location file path (absolute).
* - startLine: inclusive start line of the character range (1-based).
* - startColumn: inclusive start column of the character range (1-based).
* - endLine: inclusive end line of the character range (1-based).
* - endColumn: inclusive end column of the character range (1-based).
*
* Note that even if an alert has no matching locations for this filtering predicate, it could still
* have matching locations for other filtering predicates in this module. In that case, queries must
* still produce such an alert. An alert can be omitted only if (1) there is at least one active
* filtering predicate, and (2) it has no matching locations for any active filtering predicate.
*
* See also: `restrictAlertsTo`.
*/
extensible predicate restrictAlertsToExactLocation(
string filePath, int startLine, int startColumn, int endLine, int endColumn
);
/** Module for applying alert location filtering. */
module AlertFilteringImpl<LocationSig Location> {
pragma[nomagic]
private predicate restrictAlertsToEntireFile(string filePath) { restrictAlertsTo(filePath, 0, 0) }
pragma[nomagic]
private predicate restrictAlertsToLine(string filePath, int line) {
exists(int startLineStart, int startLineEnd |
restrictAlertsTo(filePath, startLineStart, startLineEnd) and
line = [startLineStart .. startLineEnd]
)
}
/**
* Holds if the given location is a match for one of the active filtering
* predicates in this module, or if all filtering predicates are inactive
* (which means that all alerts must be produced).
*
* Note that this predicate has a bindingset and will therefore be inlined;
* callers should include enough context to ensure efficient evaluation.
*/
bindingset[location]
predicate filterByLocation(Location location) {
not restrictAlertsTo(_, _, _) and not restrictAlertsToExactLocation(_, _, _, _, _)
or
exists(string filePath |
restrictAlertsToEntireFile(filePath) and
location.hasLocationInfo(filePath, _, _, _, _)
or
exists(int locStartLine, int locEndLine |
location.hasLocationInfo(filePath, locStartLine, _, locEndLine, _)
|
restrictAlertsToLine(pragma[only_bind_into](filePath), [locStartLine .. locEndLine])
)
)
or
// Check if an exact filter-location is fully contained in `location`.
// This is slow but only used for testing.
exists(
string filePath, int startLine, int startColumn, int endLine, int endColumn,
int filterStartLine, int filterStartColumn, int filterEndLine, int filterEndColumn
|
location.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn) and
restrictAlertsToExactLocation(filePath, filterStartLine, filterStartColumn, filterEndLine,
filterEndColumn) and
startLine <= filterStartLine and
(startLine != filterStartLine or startColumn <= filterStartColumn) and
endLine >= filterEndLine and
(endLine != filterEndLine or endColumn >= filterEndColumn)
)
}
}