Merge branch 'main' into tutorial/library-pack

This commit is contained in:
Aditya Sharad
2023-01-03 14:08:37 -08:00
committed by GitHub
406 changed files with 26663 additions and 5387 deletions

View File

@@ -0,0 +1,277 @@
# Flow summaries
Flow summaries describe how data flows through methods whose definition is not
included in the database. For example, methods in the standard library or a gem.
Say we have the following code:
```rb
x = gets
y = x.chomp
system(y)
```
This code reads a line from STDIN, strips any trailing newlines, and executes it
as a shell command. Assuming `x` is considered tainted, we want the argument `y`
to be tainted in the call to `system`.
`chomp` is a standard library method in the `String` class for which we
have no source code, so we include a flow summary for it:
```ql
private class ChompSummary extends SimpleSummarizedCallable {
ChompSummary() { this = "chomp" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "Argument[self]" and
output = "ReturnValue" and
preservesValue = false
}
}
```
The shared dataflow library will use this summary to construct a fake definition
for `chomp`. The behaviour of this definition depends on the body of
`propagatesFlowExt`. In this case, the method will propagate taint flow from the
`self` argument (i.e. the receiver) to the return value.
If `preservesValue = true` then value flow is propagated. If it is `false` then
only taint flow is propagated.
Any call to `chomp` in the database will be translated, in the dataflow graph,
to a call to this fake definition.
`input` and `output` define the "from" and "to" locations in the flow summary.
They use a custom string-based syntax which is similar to that used in `path`
column in the Models as Data format. These strings are often referred to as
access paths.
Note: The behaviour documented below is tested in
`dataflow/flow-summaries/behaviour.ql`. Where specific quirks exist, we may
reference a particular test case in this file which demonstrates the quirk.
# Syntax
Access paths consist of zero or more components separated by dots (`.`). The
permitted components differ for input and output paths. The meaning of each
component is defined relative to the implicit context of the component as
defined by the preceding access path. For example,
```
Argument[0].Element[1].ReturnValue
```
refers to the return value of the element at index 1 in the array at argument 0
of the method call.
## `Argument` and `Parameter`
The `Argument` and `Parameter` components refer respectively to an argument to a
call or a parameter of a callable. They contain one or more _specifiers_[^1] which
constrain the range of arguments/parameters that the component refers to. For
example, `Argument[0]` refers to the first argument.
If multiple specifiers are given then the result is a disjunction, meaning that
the component refers to any argument/parameter that satisfies at least one of
the specifiers. For example, `Argument[0, 1]` refers to the first and second
arguments.
### Specifiers
#### `self`
The receiver of the call.
#### `<integer>`
The argument to the method call at the position given by the integer. For
example, `Argument[0]` refers to the first argument to the call.
#### `<integer>..`
An argument to the call at a position greater or equal to the integer. For
example, `Argument[1..]` refers to all arguments except the first one. This
specifier is not available on `Parameter` components.
#### `<string>:`
A keyword argument to the call with the given name. For example,
`Argument[foo:]` refers to the keyword argument `foo:` in the call.
#### `block`
The block argument passed to the call, if any.
#### `any`
Any argument to the call, except `self` or `block` arguments.
#### `any-named`
Any keyword argument to the call.
#### `hash-splat`
The special "hash splat" argument/parameter, which is written as `**args`.
When used in an `Argument` component, this specifier refers to special dataflow
node which is constructed at the call site, containing any elements in a hash
splat argument (`**args`) along with any explicit keyword arguments (`foo:
bar`). The node behaves like a normal dataflow node for a hash, meaning that you
can access specific elements of it using the `Element` component.
For example, the following flow summary states that values flow from any keyword
arguments (including those in a hash splat) to the return value:
```ql
input = "Argument[hash-splat].Element[any]" and
output = "ReturnValue" and
preservesValue = true
```
Assuming this summary is for a global method `foo`, the following test will pass:
```rb
a = source "a"
b = source "b"
h = {a: a}
x = foo(b: b, **h)
sink x # $ hasValueFlow=a hasValueFlow=b
```
If the method returns the hash itself, you will need to use `WithElement` in
order to preserve taint/value in its elements. For example:
```ql
input = "Argument[hash-splat].WithElement[any]" and
output = "ReturnValue" and
preservesValue = true
```
```rb
a = source "a"
x = foo(a: a)
sink x[:a] # $ hasValueFlow=a
```
## `ReturnValue`
`ReturnValue` refers to the return value of the element identified in the
preceding access path. For example, `Argument[0].ReturnValue` refers to the
return value of the first argument. Of course this only makes sense if the first
argument is a callable.
## `Element`
This component refers to elements inside a collection of some sort. Typically
this is an Array or Hash. Elements are considered to have an index, which is an
integer in arrays and a symbol or string in hashes (even though hashes can have
arbitrary objects as keys). Elements can also have an unknown index, which means
we know the element exists in the collection but we don't know where.
Many of the specifiers have an optional suffix `!`. If this suffix is used then
the specifier excludes elements at unknown indices. Otherwise, these are
included by default.
### Specifiers
#### `?`
If used in an input path: an element at an unknown index. If used in an output
path: an element at any known or unkown index. In other words, `?` in an output
path means the same as `any`.
#### `any`
An element at any known or unknown index.
#### `<integer>`, `<integer>!`
An element at the index given by the integer.
#### `<integer>..`, `<integer>..!`
Any element at a known index greater or equal to the integer.
#### `<string>`, `<string>!`
An element at the index given by string. The string should match the result of
`serialize()` on the `ConstantValue` that represents the index. For a string
with contents `foo` this is `"foo"` and for a symbol `:foo` it is `:foo`. The
Ruby values `true`, `false` and `nil` can be written verbatim. See tests 31-33
for examples.
## `Field`
A "field" in the object. In practice this refers to a value stored in an
instance variable in the object. The only valid specifier is `@<string>`, where
`<string>` is the name of the instance variable. Currently we assume that a
setter call such as `x.foo = bar` means there is a field `foo` in `x`, backed by
an instance variable `@foo`.
For example, the access path `Argument[0].Field[@foo]` would refer to the value `"foo"` in
```rb
x = SomeClass.new
x.foo = "foo"
some_call(x)
```
## `WithElement`
This component restricts the set of elements that are included in the preceding
access path to to those at a specific set of indices. The specifiers are the
same as those for `Element`. It is only valid in an input path.
This component has the effect of copying all relevant elements from the input to
the output. For example, in the following summary:
```ql
input = "Argument[0].WithElement[1, 2]" and
output = "ReturnValue"
```
any data in indices 1 and 2 of the first argument will be copied to indices 1
and 2 of the return value. We use this in many Hash summaries that return the
receiver, in order to preserve any data stored in it. For example, the summary
for `Hash#to_h` is
```ql
input = "Argument[self].WithElement[any]" and
output = "ReturnValue" and
preservesValue = true
```
## `WithoutElement`
This component is used to exclude certain elements from the set included in the
preceding access path. It takes the same specifiers as `WithElement` and
`Element`. It is only valid in an input path.
This component has the effect of excluding the relevant elements when copying
from input to output. It is useful for modelling methods that remove elements
from a collection. For example to model a method that removes the first element
from the receiver, we can do so like this:
```ql
input = "Argument[self].WithoutElement[0]" and
output = "Argument[self]"
```
Note that both the input and output refer to the receiver. The effect of this
summary is that use-use flow between the receiver in the method call and a
subsequent use of the same receiver will be blocked:
```ruby
a[0] = source 0
a[1] = source 1
a.remove_first # use-use flow from `a` on this line to `a` below will be blocked.
# there will still be flow from `[post-update] a` to `a` below.
sink a[0]
sink a[1] # $ hasValueFlow=1
```
It is also important to note that in a summary such as
```ql
input = "Argument[self].WithoutElement[0]" and
output = "ReturnValue"
```
if `Argument[self]` contains data, it will be copied to `ReturnValue`. If you only want to copy data in elements, and not in the container itself, add `WithElement[any]` to the input path:
```ql
input = "Argument[self].WithoutElement[0].WithElement[any]" and
output = "ReturnValue"
```
See tests 53 and 54 for examples of this behaviour.
[^1]: I've chosen this name to avoid overloading the word "argument".

View File

@@ -1,4 +1,4 @@
/*
/**
* CodeQL library for Ruby
* Automatically generated from the tree-sitter grammar; do not edit
*/

View File

@@ -260,6 +260,12 @@ module Public {
* Holds if the neutral is auto generated.
*/
predicate isAutoGenerated() { neutralElement(this, true) }
/**
* Holds if the neutral has the given provenance where `true` is
* `generated` and `false` is `manual`.
*/
predicate hasProvenance(boolean generated) { neutralElement(this, generated) }
}
}

View File

@@ -474,9 +474,6 @@ private class TransformKeysBangSummary extends SimpleSummarizedCallable {
(
input = "Argument[self].Element[any]" and
output = "Argument[self].Element[?]"
or
input = "Argument[self].WithoutElement[any]" and
output = "Argument[self]"
) and
preservesValue = true
}

View File

@@ -5,23 +5,25 @@
* @id rb/alert-suppression
*/
private import codeql.suppression.AlertSuppression as AS
private import codeql.util.suppression.AlertSuppression as AS
private import codeql.ruby.ast.internal.TreeSitter
class SingleLineComment extends Ruby::Comment {
SingleLineComment() {
// suppression comments must be single-line
this.getLocation().getStartLine() = this.getLocation().getEndLine()
}
class AstNode extends Ruby::Token {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
class SingleLineComment extends Ruby::Comment, AstNode {
SingleLineComment() {
// suppression comments must be single-line
this.getLocation().getStartLine() = this.getLocation().getEndLine()
}
/** Gets the suppression annotation in this comment. */
string getText() { result = this.getValue().suffix(1) }
}
import AS::Make<SingleLineComment>
import AS::Make<AstNode, SingleLineComment>

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `AlertSuppression.ql` query has been updated to support the new `# codeql[query-id]` supression comments. These comments can be used to suppress an alert and must be placed on a blank line before the alert. In addition the legacy `# lgtm` and `# lgtm[query-id]` comments can now also be place on the line before an alert.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,588 @@
/**
* @kind path-problem
* This file tests that flow summaries behave as described in `ql/docs/flow-summaries.md`.
*/
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import PathGraph
private import codeql.ruby.dataflow.FlowSummary
/**
* A convenience class for defining value (c.f. taint) flow summaries.
*/
abstract private class Summary extends SimpleSummarizedCallable {
bindingset[this]
Summary() { any() }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
this.propagates(input, output) and preservesValue = true
}
abstract predicate propagates(string input, string output);
}
/**
* `Argument[self]` (input)
*/
private class S1 extends Summary {
S1() { this = "s1" }
override predicate propagates(string input, string output) {
input = "Argument[self]" and output = "ReturnValue"
}
}
/**
* `Argument[self]` (output)
*/
private class S2 extends Summary {
S2() { this = "s2" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "Argument[self]"
}
}
/**
* `Argument[<integer>]` (input, output)
*/
private class S3 extends Summary {
S3() { this = "s3" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "Argument[1]"
}
}
/**
* `Argument[<integer>..]` (input)
*/
private class S4 extends Summary {
S4() { this = "s4" }
override predicate propagates(string input, string output) {
input = "Argument[1..]" and output = "ReturnValue"
}
}
/**
* `Argument[<integer>..]` (output)
*/
private class S5 extends Summary {
S5() { this = "s5" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "Argument[2..]"
}
}
/**
* `Argument[<string>]` (input)
*/
private class S6 extends Summary {
S6() { this = "s6" }
override predicate propagates(string input, string output) {
input = "Argument[foo:]" and output = "ReturnValue"
}
}
/**
* `Argument[<string>]` (output)
*/
private class S7 extends Summary {
S7() { this = "s7" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "Argument[foo:]"
}
}
/**
* `Argument[block]` (input)
*/
private class S8 extends Summary {
S8() { this = "s8" }
override predicate propagates(string input, string output) {
input = "Argument[block].ReturnValue" and output = "ReturnValue"
}
}
/**
* `Argument[block]` (output)
*/
private class S9 extends Summary {
S9() { this = "s9" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "Argument[block].Parameter[0]"
}
}
/**
* `Argument[any]` (input) 1
*/
private class S10 extends Summary {
S10() { this = "s10" }
override predicate propagates(string input, string output) {
input = "Argument[any]" and output = "ReturnValue"
}
}
/**
* `Argument[any]` (input) 2
* This tests that access paths using `Argument[any]` do not match blocks.
* Test 10 contains an edge case example where blocks are matched, but this does
* not appear to work in general.
*/
private class S11 extends Summary {
S11() { this = "s11" }
override predicate propagates(string input, string output) {
input = "Argument[any].ReturnValue" and output = "ReturnValue"
}
}
/**
* `Argument[any]` (output)
*/
private class S12 extends Summary {
S12() { this = "s12" }
override predicate propagates(string input, string output) {
input = "Argument[self]" and output = "Argument[any]"
}
}
/**
* `Argument[any-named]` (input)
*/
private class S13 extends Summary {
S13() { this = "s13" }
override predicate propagates(string input, string output) {
input = "Argument[any-named]" and output = "ReturnValue"
}
}
/**
* `Argument[any-named]` (output)
*/
private class S14 extends Summary {
S14() { this = "s14" }
override predicate propagates(string input, string output) {
input = "Argument[self]" and output = "Argument[any-named]"
}
}
/**
* `Argument[hash-splat]` (input) 1
*/
private class S15 extends Summary {
S15() { this = "s15" }
override predicate propagates(string input, string output) {
input = "Argument[hash-splat]" and output = "ReturnValue"
}
}
/**
* `Argument[hash-splat]` (input) 2
*/
private class S16 extends Summary {
S16() { this = "s16" }
override predicate propagates(string input, string output) {
input = "Argument[hash-splat].Element[any]" and output = "ReturnValue"
}
}
/**
* `Argument[hash-splat]` (output) 1
*/
private class S17 extends Summary {
S17() { this = "s17" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "Argument[hash-splat]"
}
}
/**
* `Argument[hash-splat]` (output) 2
*/
private class S18 extends Summary {
S18() { this = "s18" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "Argument[hash-splat].Element[:foo]"
}
}
/** `Element[?]` (input) */
private class S19 extends Summary {
S19() { this = "s19" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[?]" and output = "ReturnValue"
}
}
/** `Element[?]` (output) */
private class S20 extends Summary {
S20() { this = "s20" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[?]"
}
}
/** `Element[any]` (input) */
private class S21 extends Summary {
S21() { this = "s21" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[any]" and output = "ReturnValue"
}
}
/** `Element[any]` (output) */
private class S22 extends Summary {
S22() { this = "s22" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[any]"
}
}
/** `Element[<integer>]` (input) */
private class S23 extends Summary {
S23() { this = "s23" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[0]" and output = "ReturnValue"
}
}
/** `Element[<integer>]` (output) */
private class S24 extends Summary {
S24() { this = "s24" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[0]"
}
}
/** `Element[<integer>!]` (input) */
private class S25 extends Summary {
S25() { this = "s25" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[0!]" and output = "ReturnValue"
}
}
/** `Element[<integer>!]` (output) */
private class S26 extends Summary {
S26() { this = "s26" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[0!]"
}
}
/** `Element[<integer>..]` (input) */
private class S27 extends Summary {
S27() { this = "s27" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[1..]" and output = "ReturnValue"
}
}
/** `Element[<integer>..]` (output) */
private class S28 extends Summary {
S28() { this = "s28" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[1..]"
}
}
/** `Element[<integer>..!]` (input) */
private class S29 extends Summary {
S29() { this = "s29" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[1..!]" and output = "ReturnValue"
}
}
/** `Element[<integer>..!]` (output) */
private class S30 extends Summary {
S30() { this = "s30" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[1..!]"
}
}
/**
* `Element[<string>]` (input) 1
*
* In general, the key format must match the output of `ConstantValue::serialize/0`.
* For example, symbol keys must be prefixed by `:`.
*/
private class S31 extends Summary {
S31() { this = "s31" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[:foo]" and output = "ReturnValue"
}
}
/**
* `Element[<string>]` (input) 2
*
* String keys must be wrapped double quotes.
*/
private class S32 extends Summary {
S32() { this = "s32" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[\"foo\"]" and output = "ReturnValue"
}
}
/**
* `Element[<string>]` (input) 3
*
* `nil`, `true` and `false` keys can be written verbatim.
*/
private class S33 extends Summary {
S33() { this = "s33" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[nil,true,false]" and output = "ReturnValue"
}
}
/** `Element[<string>]` (output) 1 */
private class S35 extends Summary {
S35() { this = "s35" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[:foo]"
}
}
/** `Element[<string>]` (output) 2 */
private class S36 extends Summary {
S36() { this = "s36" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[\"foo\"]"
}
}
/** `Element[<string>]` (output) 3 */
private class S37 extends Summary {
S37() { this = "s37" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[true]"
}
}
/**
* `Element[<string>!]` (input)
*/
private class S38 extends Summary {
S38() { this = "s38" }
override predicate propagates(string input, string output) {
input = "Argument[0].Element[\"foo\"!]" and output = "ReturnValue"
}
}
/**
* `Element[<string>!]` (output)
*/
private class S39 extends Summary {
S39() { this = "s39" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Element[:foo!]"
}
}
/**
* `Field[@<string>]` (input)
*/
private class S40 extends Summary {
S40() { this = "s40" }
override predicate propagates(string input, string output) {
input = "Argument[0].Field[@foo]" and output = "ReturnValue"
}
}
/**
* `Field[@<string>]` (output)
*/
private class S41 extends Summary {
S41() { this = "s41" }
override predicate propagates(string input, string output) {
input = "Argument[0]" and output = "ReturnValue.Field[@foo]"
}
}
/**
* `WithElement`
*/
private class S42 extends Summary {
S42() { this = "s42" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithElement[0]" and output = "ReturnValue"
}
}
/**
* `WithElement[!]`
*/
private class S43 extends Summary {
S43() { this = "s43" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithElement[0!]" and output = "ReturnValue"
}
}
/**
* `WithoutElement` 1
*/
private class S44 extends Summary {
S44() { this = "s44" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[0]" and output = "Argument[0]"
}
}
/**
* `WithoutElement` 2
*/
private class S45 extends Summary {
S45() { this = "s45" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[0!]" and output = "Argument[0]"
}
}
/**
* `WithoutElement` 3
*/
private class S46 extends Summary {
S46() { this = "s46" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[0]" and output = "ReturnValue"
}
}
/**
* `WithoutElement` 4
*/
private class S47 extends Summary {
S47() { this = "s47" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[:foo].WithElement[any]" and output = "ReturnValue"
}
}
/**
* `WithoutElement` 5
*/
private class S48 extends Summary {
S48() { this = "s48" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[:foo]" and output = "ReturnValue"
}
}
/**
* `WithoutElement` 6
*/
private class S49 extends Summary {
S49() { this = "s49" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[:foo!]" and output = "ReturnValue"
}
}
/**
* `WithoutElement` 7
*/
private class S50 extends Summary {
S50() { this = "s50" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[:foo]" and output = "Argument[0]"
}
}
/**
* `WithoutElement` 8
*/
private class S51 extends Summary {
S51() { this = "s51" }
override predicate propagates(string input, string output) {
input = "Argument[0].WithoutElement[:foo!]" and output = "Argument[0]"
}
}
/**
* `WithoutElement` 9
*/
private class S52 extends Summary {
S52() { this = "s52" }
override predicate propagates(string input, string output) {
input = "Argument[self].WithoutElement[:foo]" and output = "Argument[self]"
}
}
/**
* `WithoutElement` 10
*/
private class S53 extends Summary {
S53() { this = "s53" }
override predicate propagates(string input, string output) {
input = "Argument[self].WithoutElement[:foo]" and
output = "ReturnValue"
}
}
/**
* `WithoutElement` 11
*/
private class S54 extends Summary {
S54() { this = "s54" }
override predicate propagates(string input, string output) {
input = "Argument[self].WithoutElement[:foo].WithElement[any]" and
output = "ReturnValue"
}
}

View File

@@ -0,0 +1,518 @@
def m1
a = source "a"
x = a.s1()
sink x # $ hasValueFlow=a
end
def m2(x)
a = source "a"
x.s2(a)
sink x # $ hasValueFlow=a
end
def m3(x)
a = source "a"
s3(a, x)
sink x # $ hasValueFlow=a
end
def m4
sink s4("a", "b", "c")
sink s4(source "a", "b", "c")
sink s4("a", source "b", "c") # $ hasValueFlow=b SPURIOUS: hasValueFlow=c
sink s4("a", "b", source "c") # $ hasValueFlow=c
sink s4(source "a", source "b", source "c") # hasValueFlow=b hasValueFlow=c
end
def m5(x, y, z)
a = source "a"
s5(a, x, y, z)
sink x
sink y # $ hasValueFlow=a
sink z # $ hasValueFlow=a
end
def m6
sink s6(foo: source "a", bar: source "b") # $ MISSING: hasValueFlow=a
end
def m7(x)
a = source "a"
s7(a, foo: x)
sink x # $ hasValueFlow=a
end
def m8
sink(s8 { source "a" }) # $ hasValueFlow=a
sink(s8 do # $hasValueFlow=a
source "a"
end)
end
def m9
s9(source "a") { |x| sink x } # $ hasValueFlow=a
s9(source "a") do |x|
sink x # $ hasValueFlow=a
end
end
def m10
a = source "a"
sink s10(a) # $ hasValueFlow=a
sink s10(0, a) # $ hasValueFlow=a
sink s10(foo: a) # $ hasValueFlow=a
sink s10(foo: 0, bar: a) # $ hasValueFlow=a
sink (a).s10
sink s10(&a) # $ hasValueFlow=a
end
def m11
a = source "a"
sink(s11 { a })
sink(s11 do
a
end)
f = ->() { a }
sink s10(&f)
end
def m12(x, y, z, &blk)
a = source "a"
a.s12(x, y, foo: z, &blk)
sink x # $ hasValueFlow=a
sink y # $ hasValueFlow=a
sink z # $ hasValueFlow=a
sink blk
end
def m13
a = source "a"
sink s13(a)
sink s13(foo: a) # $ hasValueFlow=a
sink s13(foo: 0, bar: a) # $ hasValueFlow=a
sink a.s13
end
def m14(w, x, y, z)
a = source "a"
a.s14(w, foo: x)
a.s14(foo: y, bar: z)
sink w
sink x # $ hasValueFlow=a
sink y # $ hasValueFlow=a
sink z # $ hasValueFlow=a
end
def m15
a = source "a"
b = source "b"
sink s15(**a) # $ SPURIOUS: hasTaintFlow=a MISSING: hasValueFlow=a
sink s15(0, 1, foo: b, **a) # $ SPURIOUS: hasTaintFlow=a MISSING: hasValueFlow=a
end
def m16
a = source "a"
b = source "b"
h = { a: a, b: 1 }
sink s16(**h) # $ hasValueFlow=a
sink s16(a)
sink s16(a: a) # $ hasValueFlow=a
sink s16(b: 1)
sink s16(b: b, **h) # $ hasValueFlow=a hasValueFlow=b
end
def m17(h, x)
a = source "a"
s17(a, **h, foo: x)
sink h # $ hasValueFlow=a
sink x
end
def m18(x)
a = source "a"
s18(a, **h, foo: x)
sink h
sink h[:foo] # $ MISSING: hasValueFlow=a
sink x # $ MISSING: hasValueFlow=a
end
def m19(i)
a = source "a"
b = source "b"
h = {}
h[0] = a
h[i] = b
sink s19(h) # $ hasValueFlow=b
end
def m20(i)
a = source "a"
x = s20(a)
sink x[0] # $ hasValueFlow=a
sink x[i] # $ hasValueFlow=a
end
def m21(i)
a = source "a"
b = source "b"
h = {}
h[0] = a
h[i] = b
sink s21(h) # $ hasValueFlow=a hasValueFlow=b
end
def m22
a = source "a"
x = s22(a)
sink x[0] # $ hasValueFlow=a
sink x[i] # $ hasValueFlow=a
end
def m23(i)
a = source "a"
b = source "b"
h = []
h[0] = a
h[1] = b
sink s23(h) # $ hasValueFlow=a
end
def m24(i)
a = source "a"
x = s24(a)
sink x[0] # $ hasValueFlow=a
sink x[1]
sink x[i] # $ hasValueFlow=a
end
def m25(i)
a = source "a"
b = source "b"
h = []
h[0] = a
h[1] = b
sink s25(h) # $ hasValueFlow=a
end
def m26(i)
a = source "a"
x = s26(a)
sink x[0] # $ hasValueFlow=a
sink x[1]
sink x[i] # $ SPURIOUS: hasValueFlow=a
end
def m27(i)
a = source "a"
b = source "b"
c = source "c"
d = source "d"
h = []
h[0] = a
h[1] = b
h[2] = c
h[i] = d
sink s27(h) # $ hasValueFlow=b hasValueFlow=c hasValueFlow=d
end
def m28(i)
a = source "a"
x = s28(a)
sink x[0]
sink x[1] # $ MISSING: hasValueFlow=a
sink x[2] # $ MISSING: hasValueFlow=a
sink x[i] # $ MISSING: hasValueFlow=a
end
def m29(i)
a = source "a"
b = source "b"
c = source "c"
h = []
h[0] = a
h[1] = b
h[2] = c
h[i] = d
sink s29(h) # $ hasValueFlow=b hasValueFlow=c
end
def m30(i)
a = source "a"
x = s30(a)
sink x[0] # $ SPURIOUS: hasValueFlow=a
sink x[1] # $ hasValueFlow=a
sink x[2] # $ hasValueFlow=a
sink x[i] # $ SPURIOUS: hasValueFlow=a
end
def m31(h, i)
h[:foo] = source("a")
h[:bar] = source("b")
h[1] = source("c")
h[i] = source("d")
sink s31(h) # $ hasValueFlow=a hasValueFlow=d
end
def m32(h, i)
h[:foo] = source("a")
h["foo"] = source("b")
h[:bar] = source("c")
h[1] = source("d")
h[i] = source("e")
sink s32(h) # $ hasValueFlow=b hasValueFlow=e
end
def m33(h, i)
h[:foo] = source("a")
h["foo"] = source("b")
h[:bar] = source("c")
h[1] = source("d")
h[i] = source("e")
h[nil] = source("f")
h[true] = source("g")
h[false] = source("h")
sink s33(h) # $ hasValueFlow=e hasValueFlow=f hasValueFlow=g hasValueFlow=h
end
def m35(h, i)
x = s35(source("a"))
sink x[:foo] # $ hasValueFlow=a
sink x[:bar]
sink x[i] # $ hasValueFlow=a
end
def m36(h, i)
x = s36(source("a"))
sink x[:foo]
sink x["foo"] # $ hasValueFlow=a
sink x[:bar]
sink x[i] # $ hasValueFlow=a
end
def m37(h, i)
x = s37(source("a"))
sink x[:foo]
sink x[true] # $ hasValueFlow=a
sink x[:bar]
sink x[i] # $ hasValueFlow=a
end
def m38(h, i)
h["foo"] = source("a")
h[i] = source("b")
sink s38(h) # $ hasValueFlow=a
end
def m39(i)
x = s39(source("a"))
sink x[:foo] # $ hasValueFlow=a
sink x[i] # $ SPURIOUS: hasValueFlow=a
end
def m40
x = A.new
x.foo = source("a")
x.bar = source("b")
sink s40(x) # $ hasValueFlow=a
end
def m41
x = s41(source("a"))
sink x.foo # $ hasValueFlow=a
sink x.bar
end
def m42(i, h)
h[0] = source("a")
h[i] = source("b")
x = s42(h)
sink x[0] # $ hasValueFlow=a hasValueFlow=b
sink x[1] # $ hasValueFlow=b
sink x[i] # $ hasValueFlow=a hasValueFlow=b
end
def m43(i, h)
h[0] = source("a")
h[i] = source("b")
x = s43(h)
sink x[0] # $ hasValueFlow=a
sink x[1]
sink x[i] # $ hasValueFlow=a
end
def m44(i, h)
h[0] = source("a")
h[1] = source("b")
h[i] = source("c")
s44(h)
sink h[0]
sink h[1] # $ hasValueFlow=b
sink h[i] # $ hasValueFlow=b
end
def m45(i, h)
h[0] = source("a")
h[1] = source("b")
h[i] = source("c")
sink h[0] # $ hasValueFlow=a hasValueFlow=c
sink h[1] # $ hasValueFlow=b hasValueFlow=c
sink h[i] # $ hasValueFlow=a hasValueFlow=b hasValueFlow=c
s45(h)
sink h[0] # $ hasValueFlow=c
sink h[1] # $ hasValueFlow=b hasValueFlow=c
sink h[i] # $ hasValueFlow=b hasValueFlow=c
end
def m46(i, h)
h[0] = source("a")
h[1] = source("b")
h[i] = source("c")
sink h[0] # $ hasValueFlow=a hasValueFlow=c
sink h[1] # $ hasValueFlow=b hasValueFlow=c
sink h[i] # $ hasValueFlow=a hasValueFlow=b hasValueFlow=c
x = s46(h)
sink x[0]
sink x[1] # $ hasValueFlow=b
sink x[i] # $ hasValueFlow=b
end
def m47(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
x = s47(h)
sink x[:foo]
sink x[:bar] # $ hasValueFlow=b
end
def m48(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
x = s48(h)
sink x[:foo]
sink x[:bar] # $ hasValueFlow=b
end
def m49(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
x = s49(h)
sink x[:foo] # $ hasValueFlow=c
sink x[:bar] # $ hasValueFlow=b hasValueFlow=c
end
def m50(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
s50(h)
sink h[:foo]
sink h[:bar] # $ hasValueFlow=b
end
def m51(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
s51(h)
sink h[:foo] # $ hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
end
def m52(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
h.s52
sink h[:foo]
sink h[:bar] # $ hasValueFlow=b
end
def m53(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
x = h.s53()
sink x[:foo]
sink x[:bar] # $ hasValueFlow=b
sink(source("d").s53()) # $ hasValueFlow=d
end
def m54(i, h)
h[:foo] = source("a")
h[:bar] = source("b")
h[i] = source("c")
sink h[:foo] # $ hasValueFlow=a hasValueFlow=c
sink h[:bar] # $ hasValueFlow=b hasValueFlow=c
x = h.s54()
sink x[:foo]
sink x[:bar] # $ hasValueFlow=b
sink(source("d").s54())
end

View File

@@ -628,19 +628,21 @@ end
m38()
def m39()
def m39(x)
hash = {
:a => taint(39.1),
:b => 1,
:c => taint(39.2)
}
hash[x] = taint(39.3)
hash.transform_keys! {|key| key.to_s }
sink (hash["a"]) # $ hasValueFlow=39.1 $ hasValueFlow=39.2
sink (hash["b"]) # $ hasValueFlow=39.1 $ hasValueFlow=39.2
sink (hash["c"]) # $ hasValueFlow=39.1 $ hasValueFlow=39.2
sink (hash["a"]) # $ hasValueFlow=39.1 $ hasValueFlow=39.2 $ hasValueFlow=39.3
sink (hash["b"]) # $ hasValueFlow=39.1 $ hasValueFlow=39.2 $ hasValueFlow=39.3
sink (hash["c"]) # $ hasValueFlow=39.1 $ hasValueFlow=39.2 $ hasValueFlow=39.3
end
m39()
m39(:d)
def m40()
hash = {

View File

@@ -21,19 +21,19 @@
| hash_flow.rb:571:18:571:38 | # $ hasValueFlow=35.1 | Missing result:hasValueFlow=35.1 |
| hash_flow.rb:591:20:591:60 | # $ hasValueFlow=36.1 $ hasValueFlow=36.2 | Missing result:hasValueFlow=36.1 |
| hash_flow.rb:591:20:591:60 | # $ hasValueFlow=36.1 $ hasValueFlow=36.2 | Missing result:hasValueFlow=36.2 |
| hash_flow.rb:668:14:668:18 | value | Unexpected result: hasValueFlow=41.3 |
| hash_flow.rb:671:10:671:19 | ( ... ) | Unexpected result: hasValueFlow=41.1 |
| hash_flow.rb:702:22:702:42 | # $ hasValueFlow=42.3 | Missing result:hasValueFlow=42.3 |
| hash_flow.rb:704:22:704:42 | # $ hasValueFlow=42.4 | Missing result:hasValueFlow=42.4 |
| hash_flow.rb:774:10:774:14 | ...[...] | Unexpected result: hasValueFlow=46.1 |
| hash_flow.rb:777:10:777:14 | ...[...] | Unexpected result: hasValueFlow=46.3 |
| hash_flow.rb:779:10:779:17 | ...[...] | Unexpected result: hasValueFlow=46.1 |
| hash_flow.rb:782:10:782:17 | ...[...] | Unexpected result: hasValueFlow=46.3 |
| hash_flow.rb:839:22:839:42 | # $ hasValueFlow=48.3 | Missing result:hasValueFlow=48.3 |
| hash_flow.rb:841:22:841:42 | # $ hasValueFlow=48.4 | Missing result:hasValueFlow=48.4 |
| hash_flow.rb:901:22:901:42 | # $ hasValueFlow=50.3 | Missing result:hasValueFlow=50.3 |
| hash_flow.rb:903:22:903:42 | # $ hasValueFlow=50.4 | Missing result:hasValueFlow=50.4 |
| hash_flow.rb:931:22:931:42 | # $ hasValueFlow=51.3 | Missing result:hasValueFlow=51.3 |
| hash_flow.rb:933:22:933:42 | # $ hasValueFlow=51.4 | Missing result:hasValueFlow=51.4 |
| hash_flow.rb:961:22:961:42 | # $ hasValueFlow=52.3 | Missing result:hasValueFlow=52.3 |
| hash_flow.rb:963:22:963:42 | # $ hasValueFlow=52.4 | Missing result:hasValueFlow=52.4 |
| hash_flow.rb:670:14:670:18 | value | Unexpected result: hasValueFlow=41.3 |
| hash_flow.rb:673:10:673:19 | ( ... ) | Unexpected result: hasValueFlow=41.1 |
| hash_flow.rb:704:22:704:42 | # $ hasValueFlow=42.3 | Missing result:hasValueFlow=42.3 |
| hash_flow.rb:706:22:706:42 | # $ hasValueFlow=42.4 | Missing result:hasValueFlow=42.4 |
| hash_flow.rb:776:10:776:14 | ...[...] | Unexpected result: hasValueFlow=46.1 |
| hash_flow.rb:779:10:779:14 | ...[...] | Unexpected result: hasValueFlow=46.3 |
| hash_flow.rb:781:10:781:17 | ...[...] | Unexpected result: hasValueFlow=46.1 |
| hash_flow.rb:784:10:784:17 | ...[...] | Unexpected result: hasValueFlow=46.3 |
| hash_flow.rb:841:22:841:42 | # $ hasValueFlow=48.3 | Missing result:hasValueFlow=48.3 |
| hash_flow.rb:843:22:843:42 | # $ hasValueFlow=48.4 | Missing result:hasValueFlow=48.4 |
| hash_flow.rb:903:22:903:42 | # $ hasValueFlow=50.3 | Missing result:hasValueFlow=50.3 |
| hash_flow.rb:905:22:905:42 | # $ hasValueFlow=50.4 | Missing result:hasValueFlow=50.4 |
| hash_flow.rb:933:22:933:42 | # $ hasValueFlow=51.3 | Missing result:hasValueFlow=51.3 |
| hash_flow.rb:935:22:935:42 | # $ hasValueFlow=51.4 | Missing result:hasValueFlow=51.4 |
| hash_flow.rb:963:22:963:42 | # $ hasValueFlow=52.3 | Missing result:hasValueFlow=52.3 |
| hash_flow.rb:965:22:965:42 | # $ hasValueFlow=52.4 | Missing result:hasValueFlow=52.4 |

View File

@@ -1,48 +1,100 @@
| 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:2:1:2:32 | # lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:3:0:3:0 | 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: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:4:0:4:0 | 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:4:1:4:23 | # lgtm[@tag:exceptions] | lgtm[@tag:exceptions] | lgtm[@tag:exceptions] | Test.rb:5:0:5:0 | 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: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:6:0:6:0 | 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:6:1:6:27 | # lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | Test.rb:7:0:7:0 | 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: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:8:0:8:0 | 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:8:1:8:17 | # lgtm: blah blah | lgtm: blah blah | lgtm | Test.rb:9:0:9:0 | 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:9:1:9:31 | # lgtm blah blah #falsepositive | lgtm blah blah #falsepositive | lgtm | Test.rb:10:0:10:0 | 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:10:1:10:33 | #lgtm [rb/confusing-method-name] | lgtm [rb/confusing-method-name] | lgtm [rb/confusing-method-name] | Test.rb:11:0:11:0 | suppression range |
| Test.rb:11:1:11:8 | # lgtm[] | lgtm[] | lgtm[] | Test.rb:11:1:11:8 | suppression range |
| Test.rb:11:1:11:8 | # lgtm[] | lgtm[] | lgtm[] | Test.rb:12:0:12:0 | suppression range |
| Test.rb:13:1:13:5 | #lgtm | lgtm | lgtm | Test.rb:13:1:13:5 | suppression range |
| Test.rb:13:1:13:5 | #lgtm | lgtm | lgtm | Test.rb:14:0:14:0 | suppression range |
| Test.rb:14:1:14:6 | #\tlgtm | \tlgtm | lgtm | Test.rb:14:1:14:6 | suppression range |
| Test.rb:14:1:14:6 | #\tlgtm | \tlgtm | lgtm | Test.rb:15:0:15:0 | 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:15:1:15:33 | # lgtm\t[rb/confusing-method-name] | lgtm\t[rb/confusing-method-name] | lgtm\t[rb/confusing-method-name] | Test.rb:16:0:16:0 | suppression range |
| Test.rb:18:1:18:11 | # foo; lgtm | foo; lgtm | lgtm | Test.rb:18:1:18:11 | suppression range |
| Test.rb:18:1:18:11 | # foo; lgtm | foo; lgtm | lgtm | Test.rb:19:0:19:0 | 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:19:1:19:37 | # foo; lgtm[rb/confusing-method-name] | foo; lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:20:0:20:0 | 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:21:1:21:36 | # foo lgtm[rb/confusing-method-name] | foo lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:22:0:22:0 | 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: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:24:0:24:0 | suppression range |
| Test.rb:24:1:24:7 | # LGTM! | LGTM! | LGTM | Test.rb:24:1:24:7 | suppression range |
| Test.rb:24:1:24:7 | # LGTM! | LGTM! | LGTM | Test.rb:25:0:25:0 | 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:25:1:25:32 | # LGTM[rb/confusing-method-name] | LGTM[rb/confusing-method-name] | LGTM[rb/confusing-method-name] | Test.rb:26:0:26:0 | 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/confusing-method-name] | Test.rb:27:0:27:0 | 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: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:27:0:27:0 | 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 | Test.rb:28:0:28:0 | 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 |
| 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:28:0:28:0 | suppression range |
| Test.rb:28:1:28:31 | # codeql[js/debugger-statement] | codeql[js/debugger-statement] | lgtm[js/debugger-statement] | Test.rb:29:0:29:0 | suppression range |
| Test.rb:29:1:29:31 | # CODEQL[js/debugger-statement] | CODEQL[js/debugger-statement] | lgtm[js/debugger-statement] | Test.rb:30:0:30:0 | suppression range |
| Test.rb:30:1:30:68 | # codeql[js/debugger-statement] -- because I know better than codeql | codeql[js/debugger-statement] -- because I know better than codeql | lgtm[js/debugger-statement] | Test.rb:31:0:31:0 | 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:2:1:2:33 | # lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:3:0:3:0 | 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: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:4:0:4:0 | 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:4:1:4:24 | # lgtm[@tag:exceptions]\r | lgtm[@tag:exceptions]\r | lgtm[@tag:exceptions] | TestWindows.rb:5:0:5:0 | 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: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:6:0:6:0 | 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:6:1:6:28 | # lgtm[@expires:2017-06-11]\r | lgtm[@expires:2017-06-11]\r | lgtm[@expires:2017-06-11] | TestWindows.rb:7:0:7:0 | 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: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:8:0:8:0 | 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:8:1:8:18 | # lgtm: blah blah\r | lgtm: blah blah\r | lgtm | TestWindows.rb:9:0:9:0 | 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:9:1:9:32 | # lgtm blah blah #falsepositive\r | lgtm blah blah #falsepositive\r | lgtm | TestWindows.rb:10:0:10:0 | 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:10:1:10:34 | #lgtm [rb/confusing-method-name]\r | lgtm [rb/confusing-method-name]\r | lgtm [rb/confusing-method-name] | TestWindows.rb:11:0:11:0 | suppression range |
| TestWindows.rb:11:1:11:9 | # lgtm[]\r | lgtm[]\r | lgtm[] | TestWindows.rb:11:1:11:9 | suppression range |
| TestWindows.rb:11:1:11:9 | # lgtm[]\r | lgtm[]\r | lgtm[] | TestWindows.rb:12:0:12:0 | suppression range |
| TestWindows.rb:13:1:13:6 | #lgtm\r | lgtm\r | lgtm | TestWindows.rb:13:1:13:6 | suppression range |
| TestWindows.rb:13:1:13:6 | #lgtm\r | lgtm\r | lgtm | TestWindows.rb:14:0:14:0 | suppression range |
| TestWindows.rb:14:1:14:7 | #\tlgtm\r | \tlgtm\r | lgtm | TestWindows.rb:14:1:14:7 | suppression range |
| TestWindows.rb:14:1:14:7 | #\tlgtm\r | \tlgtm\r | lgtm | TestWindows.rb:15:0:15:0 | 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: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:16:0:16:0 | 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:18:1:18:12 | # foo; lgtm\r | foo; lgtm\r | lgtm | TestWindows.rb:19:0:19:0 | 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: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:20:0:20:0 | 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: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:22:0:22:0 | 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: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:24:0:24:0 | suppression range |
| TestWindows.rb:24:1:24:8 | # LGTM!\r | LGTM!\r | LGTM | TestWindows.rb:24:1:24:8 | suppression range |
| TestWindows.rb:24:1:24:8 | # LGTM!\r | LGTM!\r | LGTM | TestWindows.rb:25:0:25:0 | 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:25:1:25:33 | # LGTM[rb/confusing-method-name]\r | LGTM[rb/confusing-method-name]\r | LGTM[rb/confusing-method-name] | TestWindows.rb:26:0:26:0 | 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/confusing-method-name] | TestWindows.rb:27:0:27:0 | 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: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:27:0:27:0 | 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 | TestWindows.rb:28:0:28:0 | 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 |
| 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:28:0:28:0 | suppression range |
| TestWindows.rb:28:1:28:32 | # codeql[js/debugger-statement]\r | codeql[js/debugger-statement]\r | lgtm[js/debugger-statement] | TestWindows.rb:29:0:29:0 | suppression range |
| TestWindows.rb:29:1:29:32 | # CODEQL[js/debugger-statement]\r | CODEQL[js/debugger-statement]\r | lgtm[js/debugger-statement] | TestWindows.rb:30:0:30:0 | suppression range |
| TestWindows.rb:30:1:30:69 | # codeql[js/debugger-statement] -- because I know better than codeql\r | codeql[js/debugger-statement] -- because I know better than codeql\r | lgtm[js/debugger-statement] | TestWindows.rb:31:0:31:0 | suppression range |

View File

@@ -25,4 +25,8 @@ class Test end # lgtm
# LGTM[rb/confusing-method-name]
#lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]
#lgtm[rb/confusing-method-name]; lgtm
# codeql[js/debugger-statement]
# CODEQL[js/debugger-statement]
# codeql[js/debugger-statement] -- because I know better than codeql
foo # codeql[js/debugger-statement]

View File

@@ -25,4 +25,8 @@ class TestWindows end # lgtm
# LGTM[rb/confusing-method-name]
#lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]
#lgtm[rb/confusing-method-name]; lgtm
# codeql[js/debugger-statement]
# CODEQL[js/debugger-statement]
# codeql[js/debugger-statement] -- because I know better than codeql
foo # codeql[js/debugger-statement]