-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathAlertFiltering.qll
More file actions
147 lines (138 loc) · 6.5 KB
/
AlertFiltering.qll
File metadata and controls
147 lines (138 loc) · 6.5 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**
* 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 diff information is available in this evaluation. */
predicate diffInformationAvailable() {
restrictAlertsTo(_, _, _) or restrictAlertsToExactLocation(_, _, _, _, _)
}
/**
* Holds if diff information is available, and `filePath` is in the diff
* range.
*/
predicate fileIsInDiff(string filePath) {
restrictAlertsTo(filePath, _, _)
or
restrictAlertsToExactLocation(filePath, _, _, _, _)
}
/**
* 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 diffInformationAvailable()
or
locationIsInDiff(location)
}
/**
* Like `filterByLocation`, except that if there is no diff range, this
* predicate never holds.
*/
bindingset[location]
predicate locationIsInDiff(Location location) {
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)
)
}
}