mirror of
https://github.com/github/codeql.git
synced 2026-04-12 02:24:00 +02:00
Merge pull request #297 from github/aibaars/alert-suppression
Alert suppression and file classifier query
This commit is contained in:
43
ql/lib/codeql/ruby/filters/GeneratedCode.qll
Normal file
43
ql/lib/codeql/ruby/filters/GeneratedCode.qll
Normal file
@@ -0,0 +1,43 @@
|
||||
/** Provides classes for detecting generated code. */
|
||||
|
||||
private import ruby
|
||||
private import codeql.ruby.ast.internal.TreeSitter
|
||||
|
||||
/** A source file that contains generated code. */
|
||||
abstract class GeneratedCodeFile extends RubyFile { }
|
||||
|
||||
/** A file contining comments suggesting it contains generated code. */
|
||||
class GeneratedCommentFile extends GeneratedCodeFile {
|
||||
GeneratedCommentFile() { this = any(GeneratedCodeComment c).getLocation().getFile() }
|
||||
}
|
||||
|
||||
/** A comment line that indicates generated code. */
|
||||
abstract class GeneratedCodeComment extends Ruby::Comment { }
|
||||
|
||||
/**
|
||||
* A generic comment line that suggests that the file is generated.
|
||||
*/
|
||||
class GenericGeneratedCodeComment extends GeneratedCodeComment {
|
||||
GenericGeneratedCodeComment() {
|
||||
exists(string line, string entity, string was, string automatically | line = getValue() |
|
||||
entity = "file|class|art[ei]fact|module|script" and
|
||||
was = "was|is|has been" and
|
||||
automatically = "automatically |mechanically |auto[- ]?" and
|
||||
line.regexpMatch("(?i).*\\bThis (" + entity + ") (" + was + ") (" + automatically +
|
||||
")?generated\\b.*")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A comment warning against modifications. */
|
||||
class DontModifyMarkerComment extends GeneratedCodeComment {
|
||||
DontModifyMarkerComment() {
|
||||
exists(string line | line = getValue() |
|
||||
line.regexpMatch("(?i).*\\bGenerated by\\b.*\\bDo not edit\\b.*") or
|
||||
line.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `file` looks like it contains generated code. */
|
||||
predicate isGeneratedCode(GeneratedCodeFile file) { any() }
|
||||
82
ql/src/AlertSuppression.ql
Normal file
82
ql/src/AlertSuppression.ql
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @name Alert suppression
|
||||
* @description Generates information about alert suppressions.
|
||||
* @kind alert-suppression
|
||||
* @id rb/alert-suppression
|
||||
*/
|
||||
|
||||
import ruby
|
||||
import codeql.ruby.ast.internal.TreeSitter
|
||||
|
||||
/**
|
||||
* An alert suppression comment.
|
||||
*/
|
||||
class SuppressionComment extends Ruby::Comment {
|
||||
string annotation;
|
||||
|
||||
SuppressionComment() {
|
||||
// suppression comments must be single-line
|
||||
this.getLocation().getStartLine() = this.getLocation().getEndLine() and
|
||||
exists(string text | text = commentText(this) |
|
||||
// match `lgtm[...]` anywhere in the comment
|
||||
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)
|
||||
or
|
||||
// match `lgtm` at the start of the comment and after semicolon
|
||||
annotation = text.regexpFind("(?i)(?<=^|;)\\s*lgtm(?!\\B|\\s*\\[)", _, _).trim()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text of this suppression comment.
|
||||
*/
|
||||
string getText() { result = commentText(this) }
|
||||
|
||||
/** Gets the suppression annotation in this comment. */
|
||||
string getAnnotation() { result = annotation }
|
||||
|
||||
/**
|
||||
* Holds if this comment applies to the range from column `startcolumn` of line `startline`
|
||||
* to column `endcolumn` of line `endline` in file `filepath`.
|
||||
*/
|
||||
predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and
|
||||
startcolumn = 1
|
||||
}
|
||||
|
||||
/** Gets the scope of this suppression. */
|
||||
SuppressionScope getScope() { this = result.getSuppressionComment() }
|
||||
}
|
||||
|
||||
private string commentText(Ruby::Comment comment) { result = comment.getValue().suffix(1) }
|
||||
|
||||
/**
|
||||
* The scope of an alert suppression comment.
|
||||
*/
|
||||
class SuppressionScope extends @ruby_token_comment {
|
||||
SuppressionScope() { this instanceof SuppressionComment }
|
||||
|
||||
/** Gets a suppression comment with this scope. */
|
||||
SuppressionComment getSuppressionComment() { result = this }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "suppression range" }
|
||||
}
|
||||
|
||||
from SuppressionComment c
|
||||
select c, // suppression comment
|
||||
c.getText(), // text of suppression comment (excluding delimiters)
|
||||
c.getAnnotation(), // text of suppression annotation
|
||||
c.getScope() // scope of suppression
|
||||
20
ql/src/filters/ClassifyFiles.ql
Normal file
20
ql/src/filters/ClassifyFiles.ql
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @name Classify files
|
||||
* @description This query produces a list of all files in a database
|
||||
* that are classified as generated code or test code.
|
||||
*
|
||||
* Used by LGTM.
|
||||
* @kind file-classifier
|
||||
* @id rb/file-classifier
|
||||
*/
|
||||
|
||||
import ruby
|
||||
import codeql.ruby.filters.GeneratedCode
|
||||
|
||||
predicate classify(File f, string category) {
|
||||
f instanceof GeneratedCodeFile and category = "generated"
|
||||
}
|
||||
|
||||
from File f, string category
|
||||
where classify(f, category)
|
||||
select f, category
|
||||
1
ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
1
ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestWindows.java eol=crlf
|
||||
@@ -0,0 +1,48 @@
|
||||
| Test.rb:1:16:1:21 | # lgtm | lgtm | lgtm | Test.rb:1:1:1:21 | suppression range |
|
||||
| Test.rb:2:1:2:32 | # lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:2:1:2:32 | suppression range |
|
||||
| Test.rb:3:1:3:65 | # lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | Test.rb:3:1:3:65 | suppression range |
|
||||
| Test.rb:4:1:4:23 | # lgtm[@tag:exceptions] | lgtm[@tag:exceptions] | lgtm[@tag:exceptions] | Test.rb:4:1:4:23 | suppression range |
|
||||
| Test.rb:5:1:5:48 | # lgtm[@tag:exceptions,rb/confusing-method-name] | lgtm[@tag:exceptions,rb/confusing-method-name] | lgtm[@tag:exceptions,rb/confusing-method-name] | Test.rb:5:1:5:48 | suppression range |
|
||||
| Test.rb:6:1:6:27 | # lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | Test.rb:6:1:6:27 | suppression range |
|
||||
| Test.rb:7:1:7:78 | # lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm | lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm | lgtm[rb/confusing-method-name] | Test.rb:7:1:7:78 | suppression range |
|
||||
| Test.rb:8:1:8:17 | # lgtm: blah blah | lgtm: blah blah | lgtm | Test.rb:8:1:8:17 | suppression range |
|
||||
| Test.rb:9:1:9:31 | # lgtm blah blah #falsepositive | lgtm blah blah #falsepositive | lgtm | Test.rb:9:1:9:31 | suppression range |
|
||||
| Test.rb:10:1:10:33 | #lgtm [rb/confusing-method-name] | lgtm [rb/confusing-method-name] | lgtm [rb/confusing-method-name] | Test.rb:10:1:10:33 | suppression range |
|
||||
| Test.rb:11:1:11:8 | # lgtm[] | lgtm[] | lgtm[] | Test.rb:11:1:11:8 | suppression range |
|
||||
| Test.rb:13:1:13:5 | #lgtm | lgtm | lgtm | Test.rb:13:1:13:5 | suppression range |
|
||||
| Test.rb:14:1:14:6 | #\tlgtm | \tlgtm | lgtm | Test.rb:14:1:14:6 | suppression range |
|
||||
| Test.rb:15:1:15:33 | # lgtm\t[rb/confusing-method-name] | lgtm\t[rb/confusing-method-name] | lgtm\t[rb/confusing-method-name] | Test.rb:15:1:15:33 | suppression range |
|
||||
| Test.rb:18:1:18:11 | # foo; lgtm | foo; lgtm | lgtm | Test.rb:18:1:18:11 | suppression range |
|
||||
| Test.rb:19:1:19:37 | # foo; lgtm[rb/confusing-method-name] | foo; lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:19:1:19:37 | suppression range |
|
||||
| Test.rb:21:1:21:36 | # foo lgtm[rb/confusing-method-name] | foo lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:21:1:21:36 | suppression range |
|
||||
| Test.rb:23:1:23:40 | # foo lgtm[rb/confusing-method-name] bar | foo lgtm[rb/confusing-method-name] bar | lgtm[rb/confusing-method-name] | Test.rb:23:1:23:40 | suppression range |
|
||||
| Test.rb:24:1:24:7 | # LGTM! | LGTM! | LGTM | Test.rb:24:1:24:7 | suppression range |
|
||||
| Test.rb:25:1:25:32 | # LGTM[rb/confusing-method-name] | LGTM[rb/confusing-method-name] | LGTM[rb/confusing-method-name] | Test.rb:25:1:25:32 | suppression range |
|
||||
| Test.rb:26:1:26:73 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name] | Test.rb:26:1:26:73 | suppression range |
|
||||
| Test.rb:26:1:26:73 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/non-short-circuit-evaluation] | Test.rb:26:1:26:73 | suppression range |
|
||||
| Test.rb:27:1:27:37 | #lgtm[rb/confusing-method-name]; lgtm | lgtm[rb/confusing-method-name]; lgtm | lgtm | Test.rb:27:1:27:37 | suppression range |
|
||||
| Test.rb:27:1:27:37 | #lgtm[rb/confusing-method-name]; lgtm | lgtm[rb/confusing-method-name]; lgtm | lgtm[rb/confusing-method-name] | Test.rb:27:1:27:37 | suppression range |
|
||||
| TestWindows.rb:1:23:1:29 | # lgtm\r | lgtm\r | lgtm | TestWindows.rb:1:1:1:29 | suppression range |
|
||||
| TestWindows.rb:2:1:2:33 | # lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:2:1:2:33 | suppression range |
|
||||
| TestWindows.rb:3:1:3:66 | # lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | TestWindows.rb:3:1:3:66 | suppression range |
|
||||
| TestWindows.rb:4:1:4:24 | # lgtm[@tag:exceptions]\r | lgtm[@tag:exceptions]\r | lgtm[@tag:exceptions] | TestWindows.rb:4:1:4:24 | suppression range |
|
||||
| TestWindows.rb:5:1:5:49 | # lgtm[@tag:exceptions,rb/confusing-method-name]\r | lgtm[@tag:exceptions,rb/confusing-method-name]\r | lgtm[@tag:exceptions,rb/confusing-method-name] | TestWindows.rb:5:1:5:49 | suppression range |
|
||||
| TestWindows.rb:6:1:6:28 | # lgtm[@expires:2017-06-11]\r | lgtm[@expires:2017-06-11]\r | lgtm[@expires:2017-06-11] | TestWindows.rb:6:1:6:28 | suppression range |
|
||||
| TestWindows.rb:7:1:7:79 | # lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm\r | lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm\r | lgtm[rb/confusing-method-name] | TestWindows.rb:7:1:7:79 | suppression range |
|
||||
| TestWindows.rb:8:1:8:18 | # lgtm: blah blah\r | lgtm: blah blah\r | lgtm | TestWindows.rb:8:1:8:18 | suppression range |
|
||||
| TestWindows.rb:9:1:9:32 | # lgtm blah blah #falsepositive\r | lgtm blah blah #falsepositive\r | lgtm | TestWindows.rb:9:1:9:32 | suppression range |
|
||||
| TestWindows.rb:10:1:10:34 | #lgtm [rb/confusing-method-name]\r | lgtm [rb/confusing-method-name]\r | lgtm [rb/confusing-method-name] | TestWindows.rb:10:1:10:34 | suppression range |
|
||||
| TestWindows.rb:11:1:11:9 | # lgtm[]\r | lgtm[]\r | lgtm[] | TestWindows.rb:11:1:11:9 | suppression range |
|
||||
| TestWindows.rb:13:1:13:6 | #lgtm\r | lgtm\r | lgtm | TestWindows.rb:13:1:13:6 | suppression range |
|
||||
| TestWindows.rb:14:1:14:7 | #\tlgtm\r | \tlgtm\r | lgtm | TestWindows.rb:14:1:14:7 | suppression range |
|
||||
| TestWindows.rb:15:1:15:34 | # lgtm\t[rb/confusing-method-name]\r | lgtm\t[rb/confusing-method-name]\r | lgtm\t[rb/confusing-method-name] | TestWindows.rb:15:1:15:34 | suppression range |
|
||||
| TestWindows.rb:18:1:18:12 | # foo; lgtm\r | foo; lgtm\r | lgtm | TestWindows.rb:18:1:18:12 | suppression range |
|
||||
| TestWindows.rb:19:1:19:38 | # foo; lgtm[rb/confusing-method-name]\r | foo; lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:19:1:19:38 | suppression range |
|
||||
| TestWindows.rb:21:1:21:37 | # foo lgtm[rb/confusing-method-name]\r | foo lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:21:1:21:37 | suppression range |
|
||||
| TestWindows.rb:23:1:23:41 | # foo lgtm[rb/confusing-method-name] bar\r | foo lgtm[rb/confusing-method-name] bar\r | lgtm[rb/confusing-method-name] | TestWindows.rb:23:1:23:41 | suppression range |
|
||||
| TestWindows.rb:24:1:24:8 | # LGTM!\r | LGTM!\r | LGTM | TestWindows.rb:24:1:24:8 | suppression range |
|
||||
| TestWindows.rb:25:1:25:33 | # LGTM[rb/confusing-method-name]\r | LGTM[rb/confusing-method-name]\r | LGTM[rb/confusing-method-name] | TestWindows.rb:25:1:25:33 | suppression range |
|
||||
| TestWindows.rb:26:1:26:74 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:26:1:26:74 | suppression range |
|
||||
| TestWindows.rb:26:1:26:74 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/non-short-circuit-evaluation] | TestWindows.rb:26:1:26:74 | suppression range |
|
||||
| TestWindows.rb:27:1:27:38 | #lgtm[rb/confusing-method-name]; lgtm\r | lgtm[rb/confusing-method-name]; lgtm\r | lgtm | TestWindows.rb:27:1:27:38 | suppression range |
|
||||
| TestWindows.rb:27:1:27:38 | #lgtm[rb/confusing-method-name]; lgtm\r | lgtm[rb/confusing-method-name]; lgtm\r | lgtm[rb/confusing-method-name] | TestWindows.rb:27:1:27:38 | suppression range |
|
||||
@@ -0,0 +1 @@
|
||||
AlertSuppression.ql
|
||||
28
ql/test/query-tests/AlertSuppression/Test.rb
Normal file
28
ql/test/query-tests/AlertSuppression/Test.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
class Test end # lgtm
|
||||
# lgtm[rb/confusing-method-name]
|
||||
# lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]
|
||||
# lgtm[@tag:exceptions]
|
||||
# lgtm[@tag:exceptions,rb/confusing-method-name]
|
||||
# lgtm[@expires:2017-06-11]
|
||||
# lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm
|
||||
# lgtm: blah blah
|
||||
# lgtm blah blah #falsepositive
|
||||
#lgtm [rb/confusing-method-name]
|
||||
# lgtm[]
|
||||
# lgtmfoo
|
||||
#lgtm
|
||||
# lgtm
|
||||
# lgtm [rb/confusing-method-name]
|
||||
# foolgtm[rb/confusing-method-name]
|
||||
# foolgtm
|
||||
# foo; lgtm
|
||||
# foo; lgtm[rb/confusing-method-name]
|
||||
# foo lgtm
|
||||
# foo lgtm[rb/confusing-method-name]
|
||||
# foo lgtm bar
|
||||
# foo lgtm[rb/confusing-method-name] bar
|
||||
# LGTM!
|
||||
# LGTM[rb/confusing-method-name]
|
||||
#lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]
|
||||
#lgtm[rb/confusing-method-name]; lgtm
|
||||
|
||||
28
ql/test/query-tests/AlertSuppression/TestWindows.rb
Normal file
28
ql/test/query-tests/AlertSuppression/TestWindows.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
class TestWindows end # lgtm
|
||||
# lgtm[rb/confusing-method-name]
|
||||
# lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]
|
||||
# lgtm[@tag:exceptions]
|
||||
# lgtm[@tag:exceptions,rb/confusing-method-name]
|
||||
# lgtm[@expires:2017-06-11]
|
||||
# lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm
|
||||
# lgtm: blah blah
|
||||
# lgtm blah blah #falsepositive
|
||||
#lgtm [rb/confusing-method-name]
|
||||
# lgtm[]
|
||||
# lgtmfoo
|
||||
#lgtm
|
||||
# lgtm
|
||||
# lgtm [rb/confusing-method-name]
|
||||
# foolgtm[rb/confusing-method-name]
|
||||
# foolgtm
|
||||
# foo; lgtm
|
||||
# foo; lgtm[rb/confusing-method-name]
|
||||
# foo lgtm
|
||||
# foo lgtm[rb/confusing-method-name]
|
||||
# foo lgtm bar
|
||||
# foo lgtm[rb/confusing-method-name] bar
|
||||
# LGTM!
|
||||
# LGTM[rb/confusing-method-name]
|
||||
#lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]
|
||||
#lgtm[rb/confusing-method-name]; lgtm
|
||||
|
||||
Reference in New Issue
Block a user