Merge branch 'main' into maikypedia/ldap-improper-auth

This commit is contained in:
Maiky
2023-08-03 16:49:30 +02:00
committed by GitHub
3594 changed files with 171595 additions and 111833 deletions

View File

@@ -4,14 +4,15 @@
* Example for a test.ql:
* ```ql
* import TestUtilities.InlineFlowTest
* import DefaultFlowTest
* import PathGraph
*
* from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
* where conf.hasFlowPath(source, sink)
* from PathNode source, PathNode sink
* where flowPath(source, sink)
* select sink, source, sink, "$@", source, source.toString()
* ```
*
* To declare expecations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files.
* To declare expectations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files.
* Example of the corresponding test file, e.g. test.rb
* ```rb
* s = source(1)
@@ -20,14 +21,10 @@
* sink(t); // $ hasTaintFlow=2
* ```
*
* If you're not interested in a specific flow type, you can disable either value or taint flow expectations as follows:
* ```ql
* class HasFlowTest extends InlineFlowTest {
* override DataFlow::Configuration getTaintFlowConfig() { none() }
*
* override DataFlow::Configuration getValueFlowConfig() { none() }
* }
* ```
* If you are only interested in value flow, then instead of importing `DefaultFlowTest`, you can import
* `ValueFlowTest<DefaultFlowConfig>`. Similarly, if you are only interested in taint flow, then instead of
* importing `DefaultFlowTest`, you can import `TaintFlowTest<DefaultFlowConfig>`. In both cases
* `DefaultFlowConfig` can be replaced by another implementation of `DataFlow::ConfigSig`.
*
* If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`.
*/
@@ -38,72 +35,62 @@ import codeql.ruby.TaintTracking
import TestUtilities.InlineExpectationsTest
import TestUtilities.InlineFlowTestUtil
class DefaultValueFlowConf extends DataFlow::Configuration {
DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" }
module DefaultFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { defaultSource(source) }
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
predicate isSink(DataFlow::Node sink) { defaultSink(sink) }
override predicate isSink(DataFlow::Node n) { defaultSink(n) }
override int fieldFlowBranchLimit() { result = 1000 }
int fieldFlowBranchLimit() { result = 1000 }
}
class DefaultTaintFlowConf extends TaintTracking::Configuration {
DefaultTaintFlowConf() { this = "qltest:defaultTaintFlowConf" }
private module NoFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { none() }
override predicate isSource(DataFlow::Node n) { defaultSource(n) }
override predicate isSink(DataFlow::Node n) { defaultSink(n) }
override int fieldFlowBranchLimit() { result = 1000 }
predicate isSink(DataFlow::Node sink) { none() }
}
class InlineFlowTest extends InlineExpectationsTest {
InlineFlowTest() { this = "HasFlowTest" }
module FlowTest<DataFlow::ConfigSig ValueFlowConfig, DataFlow::ConfigSig TaintFlowConfig> {
module ValueFlow = DataFlow::Global<ValueFlowConfig>;
override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
module TaintFlow = TaintTracking::Global<TaintFlowConfig>;
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasValueFlow" and
exists(DataFlow::Node src, DataFlow::Node sink | this.getValueFlowConfig().hasFlow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
or
tag = "hasTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
this.getTaintFlowConfig().hasFlow(src, sink) and
not this.getValueFlowConfig().hasFlow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
}
private module InlineTest implements TestSig {
string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) }
DataFlow::Configuration getTaintFlowConfig() { result = any(DefaultTaintFlowConf config) }
}
module PathGraph {
private import DataFlow::PathGraph as PG
private class PathNode extends DataFlow::PathNode {
PathNode() {
this.getConfiguration() =
[any(InlineFlowTest t).getValueFlowConfig(), any(InlineFlowTest t).getTaintFlowConfig()]
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasValueFlow" and
exists(DataFlow::Node src, DataFlow::Node sink | ValueFlow::flow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
or
tag = "hasTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
TaintFlow::flow(src, sink) and not ValueFlow::flow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
}
}
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { PG::edges(a, b) }
import MakeTest<InlineTest>
import DataFlow::MergePathGraph<ValueFlow::PathNode, TaintFlow::PathNode, ValueFlow::PathGraph, TaintFlow::PathGraph>
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) { PG::nodes(n, key, val) }
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
PG::subpaths(arg, par, ret, out)
predicate flowPath(PathNode source, PathNode sink) {
ValueFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) or
TaintFlow::flowPath(source.asPathNode2(), sink.asPathNode2())
}
}
module DefaultFlowTest = FlowTest<DefaultFlowConfig, DefaultFlowConfig>;
module ValueFlowTest<DataFlow::ConfigSig ValueFlowConfig> {
import FlowTest<ValueFlowConfig, NoFlowConfig>
}
module TaintFlowTest<DataFlow::ConfigSig TaintFlowConfig> {
import FlowTest<NoFlowConfig, TaintFlowConfig>
}

View File

@@ -15,12 +15,10 @@ DataFlow::LocalSourceNode track(DataFlow::CallNode source) {
result = track(TypeTracker::end(), source)
}
class TypeTrackingFlowTest extends InlineExpectationsTest {
TypeTrackingFlowTest() { this = "TypeTrackingFlowTest" }
module TypeTrackingFlowTest implements TestSig {
string getARelevantTag() { result = "hasValueFlow" }
override string getARelevantTag() { result = "hasValueFlow" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node sink, DataFlow::Node source |
defaultSink(sink) and
track(source).flowsTo(sink) and
@@ -31,3 +29,5 @@ class TypeTrackingFlowTest extends InlineExpectationsTest {
)
}
}
import MakeTest<TypeTrackingFlowTest>

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -2,17 +2,15 @@ import codeql.ruby.AST
import codeql.ruby.Concepts
import TestUtilities.InlineExpectationsTest
class CryptographicOperationTest extends InlineExpectationsTest {
CryptographicOperationTest() { this = "CryptographicOperationTest" }
override string getARelevantTag() {
module CryptographicOperationTest implements TestSig {
string getARelevantTag() {
result in [
"CryptographicOperation", "CryptographicOperationInput", "CryptographicOperationAlgorithm",
"CryptographicOperationBlockMode"
]
}
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Cryptography::CryptographicOperation cryptoOperation |
location = cryptoOperation.getLocation() and
(
@@ -31,3 +29,5 @@ class CryptographicOperationTest extends InlineExpectationsTest {
)
}
}
import MakeTest<CryptographicOperationTest>

View File

@@ -1,8 +1,8 @@
classMethodCalls
| test1.rb:58:1:58:8 | Use getMember("M1").getMember("C1").getMethod("m").getReturn() |
| test1.rb:59:1:59:8 | Use getMember("M2").getMember("C3").getMethod("m").getReturn() |
| test1.rb:58:1:58:8 | ForwardNode(call to m) |
| test1.rb:59:1:59:8 | ForwardNode(call to m) |
instanceMethodCalls
| test1.rb:61:1:61:12 | Use getMember("M1").getMember("C1").getMethod("new").getReturn().getMethod("m").getReturn() |
| test1.rb:62:1:62:12 | Use getMember("M2").getMember("C3").getMethod("new").getReturn().getMethod("m").getReturn() |
| test1.rb:61:1:61:12 | ForwardNode(call to m) |
| test1.rb:62:1:62:12 | ForwardNode(call to m) |
flowThroughArray
| test1.rb:73:1:73:10 | call to m |

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -0,0 +1,77 @@
import ruby
import codeql.ruby.ast.internal.TreeSitter
import codeql.ruby.dataflow.internal.AccessPathSyntax
import codeql.ruby.frameworks.data.internal.ApiGraphModels
import codeql.ruby.ApiGraphs
import TestUtilities.InlineExpectationsTest
class AccessPathFromExpectation extends AccessPath::Range {
AccessPathFromExpectation() { hasExpectationWithValue(_, this) }
}
API::Node evaluatePath(AccessPath path, int n) {
path instanceof AccessPathFromExpectation and
n = 1 and
exists(AccessPathToken token | token = path.getToken(0) |
token.getName() = "Member" and
result = API::getTopLevelMember(token.getAnArgument())
or
token.getName() = "Method" and
result = API::getTopLevelCall(token.getAnArgument())
or
token.getName() = "EntryPoint" and
result = token.getAnArgument().(API::EntryPoint).getANode()
)
or
result = getSuccessorFromNode(evaluatePath(path, n - 1), path.getToken(n - 1))
or
result = getSuccessorFromInvoke(evaluatePath(path, n - 1), path.getToken(n - 1))
or
// TODO this is a workaround, support parsing of Method['[]'] instead
path.getToken(n - 1).getName() = "MethodBracket" and
result = evaluatePath(path, n - 1).getMethod("[]")
}
API::Node evaluatePath(AccessPath path) { result = evaluatePath(path, path.getNumToken()) }
module ApiUseTest implements TestSig {
string getARelevantTag() { result = ["source", "sink", "call", "reachableFromSource"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
// All results are considered optional
none()
}
predicate hasOptionalResult(Location location, string element, string tag, string value) {
exists(API::Node apiNode, DataFlow::Node dataflowNode |
apiNode = evaluatePath(value) and
(
tag = "source" and dataflowNode = apiNode.asSource()
or
tag = "reachableFromSource" and dataflowNode = apiNode.getAValueReachableFromSource()
or
tag = "sink" and dataflowNode = apiNode.asSink()
or
tag = "call" and dataflowNode = apiNode.asCall()
) and
location = dataflowNode.getLocation() and
element = dataflowNode.toString()
)
}
}
import MakeTest<ApiUseTest>
class CustomEntryPointCall extends API::EntryPoint {
CustomEntryPointCall() { this = "CustomEntryPointCall" }
override DataFlow::CallNode getACall() { result.getMethodName() = "customEntryPointCall" }
}
class CustomEntryPointUse extends API::EntryPoint {
CustomEntryPointUse() { this = "CustomEntryPointUse" }
override DataFlow::LocalSourceNode getASource() {
result.(DataFlow::CallNode).getMethodName() = "customEntryPointUse"
}
}

View File

@@ -1,39 +1,39 @@
Something.foo.withCallback do |a, b| #$ use=getMember("Something").getMethod("foo").getReturn()
a.something #$ use=getMember("Something").getMethod("foo").getReturn().getMethod("withCallback").getBlock().getParameter(0).getMethod("something").getReturn()
b.somethingElse #$ use=getMember("Something").getMethod("foo").getReturn().getMethod("withCallback").getBlock().getParameter(1).getMethod("somethingElse").getReturn()
end #$ use=getMember("Something").getMethod("foo").getReturn().getMethod("withCallback").getReturn()
Something.foo.withCallback do |a, b| #$ source=Member[Something].Method[foo].ReturnValue
a.something #$ source=Member[Something].Method[foo].ReturnValue.Method[withCallback].Argument[block].Argument[0].Method[something].ReturnValue
b.somethingElse #$ source=Member[Something].Method[foo].ReturnValue.Method[withCallback].Argument[block].Argument[1].Method[somethingElse].ReturnValue
end #$ source=Member[Something].Method[foo].ReturnValue.Method[withCallback].ReturnValue
Something.withNamedArg do |a:, b: nil| #$ use=getMember("Something")
a.something #$ use=getMember("Something").getMethod("withNamedArg").getBlock().getKeywordParameter("a").getMethod("something").getReturn()
b.somethingElse #$ use=getMember("Something").getMethod("withNamedArg").getBlock().getKeywordParameter("b").getMethod("somethingElse").getReturn()
end #$ use=getMember("Something").getMethod("withNamedArg").getReturn()
Something.withNamedArg do |a:, b: nil| #$ source=Member[Something]
a.something #$ source=Member[Something].Method[withNamedArg].Argument[block].Parameter[a:].Method[something].ReturnValue
b.somethingElse #$ source=Member[Something].Method[withNamedArg].Argument[block].Parameter[b:].Method[somethingElse].ReturnValue
end #$ source=Member[Something].Method[withNamedArg].ReturnValue
Something.withLambda ->(a, b) { #$ use=getMember("Something")
a.something #$ use=getMember("Something").getMethod("withLambda").getParameter(0).getParameter(0).getMethod("something").getReturn()
b.something #$ use=getMember("Something").getMethod("withLambda").getParameter(0).getParameter(1).getMethod("something").getReturn()
} #$ use=getMember("Something").getMethod("withLambda").getReturn()
Something.withLambda ->(a, b) { #$ source=Member[Something]
a.something #$ source=Member[Something].Method[withLambda].Argument[0].Parameter[0].Method[something].ReturnValue
b.something #$ source=Member[Something].Method[withLambda].Argument[0].Parameter[1].Method[something].ReturnValue
} #$ source=Member[Something].Method[withLambda].ReturnValue
Something.namedCallback( #$ use=getMember("Something")
Something.namedCallback( #$ source=Member[Something]
onEvent: ->(a, b) {
a.something #$ use=getMember("Something").getMethod("namedCallback").getKeywordParameter("onEvent").getParameter(0).getMethod("something").getReturn()
b.something #$ use=getMember("Something").getMethod("namedCallback").getKeywordParameter("onEvent").getParameter(1).getMethod("something").getReturn()
a.something #$ source=Member[Something].Method[namedCallback].Argument[onEvent:].Parameter[0].Method[something].ReturnValue
b.something #$ source=Member[Something].Method[namedCallback].Argument[onEvent:].Parameter[1].Method[something].ReturnValue
}
) #$ use=getMember("Something").getMethod("namedCallback").getReturn()
) #$ source=Member[Something].Method[namedCallback].ReturnValue
Something.nestedCall1 do |a| #$ use=getMember("Something")
a.nestedCall2 do |b:| #$ use=getMember("Something").getMethod("nestedCall1").getBlock().getParameter(0)
b.something #$ use=getMember("Something").getMethod("nestedCall1").getBlock().getParameter(0).getMethod("nestedCall2").getBlock().getKeywordParameter("b").getMethod("something").getReturn()
end #$ use=getMember("Something").getMethod("nestedCall1").getBlock().getParameter(0).getMethod("nestedCall2").getReturn()
end #$ use=getMember("Something").getMethod("nestedCall1").getReturn()
Something.nestedCall1 do |a| #$ source=Member[Something]
a.nestedCall2 do |b:| #$ reachableFromSource=Member[Something].Method[nestedCall1].Argument[block].Parameter[0]
b.something #$ source=Member[Something].Method[nestedCall1].Argument[block].Parameter[0].Method[nestedCall2].Argument[block].Parameter[b:].Method[something].ReturnValue
end #$ source=Member[Something].Method[nestedCall1].Argument[block].Parameter[0].Method[nestedCall2].ReturnValue
end #$ source=Member[Something].Method[nestedCall1].ReturnValue
def getCallback()
->(x) {
x.something #$ use=getMember("Something").getMethod("indirectCallback").getParameter(0).getParameter(0).getMethod("something").getReturn()
x.something #$ source=Member[Something].Method[indirectCallback].Argument[0].Parameter[0].Method[something].ReturnValue
}
end
Something.indirectCallback(getCallback()) #$ use=getMember("Something").getMethod("indirectCallback").getReturn()
Something.indirectCallback(getCallback()) #$ source=Member[Something].Method[indirectCallback].ReturnValue
Something.withMixed do |a, *args, b| #$ use=getMember("Something")
a.something #$ use=getMember("Something").getMethod("withMixed").getBlock().getParameter(0).getMethod("something").getReturn()
Something.withMixed do |a, *args, b| #$ source=Member[Something]
a.something #$ source=Member[Something].Method[withMixed].Argument[block].Parameter[0].Method[something].ReturnValue
# b.something # not currently handled correctly
end #$ use=getMember("Something").getMethod("withMixed").getReturn()
end #$ source=Member[Something].Method[withMixed].ReturnValue

View File

@@ -0,0 +1,31 @@
def chained_access1
Something.foo [[[
'sink' # $ sink=Member[Something].Method[foo].Argument[0].Element[0].Element[0].Element[0]
]]]
end
def chained_access2
array = []
array[0] = [[
'sink' # $ sink=Member[Something].Method[foo].Argument[0].Element[0].Element[0].Element[0]
]]
Something.foo array
end
def chained_access3
array = [[]]
array[0][0] = [
'sink' # $ sink=Member[Something].Method[foo].Argument[0].Element[0].Element[0].Element[0]
]
Something.foo array
end
def chained_access4
Something.foo {
:one => {
:two => {
:three => 'sink' # $ sink=Member[Something].Method[foo].Argument[0].Element[:one].Element[:two].Element[:three]
}
}
}
end

View File

@@ -0,0 +1,11 @@
Foo.bar proc { |x|
x # $ reachableFromSource=Member[Foo].Method[bar].Argument[0].Parameter[0]
}
Foo.bar lambda { |x|
x # $ reachableFromSource=Member[Foo].Method[bar].Argument[0].Parameter[0]
}
Foo.bar Proc.new { |x|
x # $ reachableFromSource=Member[Foo].Method[bar].Argument[0].Parameter[0]
}

View File

@@ -0,0 +1,64 @@
class BaseClass
def inheritedInstanceMethod
yield "taint" # $ sink=Member[Something].Method[foo].Argument[block].ReturnValue.Method[inheritedInstanceMethod].Parameter[block].Argument[0]
end
def self.inheritedSingletonMethod
yield "taint" # $ sink=Member[Something].Method[bar].Argument[block].ReturnValue.Method[inheritedSingletonMethod].Parameter[block].Argument[0]
end
end
class ClassWithCallbacks < BaseClass
def instanceMethod
yield "taint" # $ sink=Member[Something].Method[foo].Argument[block].ReturnValue.Method[instanceMethod].Parameter[block].Argument[0]
end
def self.singletonMethod
yield "bar" # $ sink=Member[Something].Method[bar].Argument[block].ReturnValue.Method[singletonMethod].Parameter[block].Argument[0]
end
def escapeSelf
Something.baz { self }
end
def self.escapeSingletonSelf
Something.baz { self }
end
def self.foo x
x # $ reachableFromSource=Member[BaseClass].Method[foo].Parameter[0]
x # $ reachableFromSource=Member[ClassWithCallbacks].Method[foo].Parameter[0]
x # $ reachableFromSource=Member[Subclass].Method[foo].Parameter[0]
end
def bar x
x # $ reachableFromSource=Member[BaseClass].Instance.Method[bar].Parameter[0]
x # $ reachableFromSource=Member[ClassWithCallbacks].Instance.Method[bar].Parameter[0]
x # $ reachableFromSource=Member[Subclass].Instance.Method[bar].Parameter[0]
end
end
class Subclass < ClassWithCallbacks
def instanceMethodInSubclass
yield "bar" # $ sink=Member[Something].Method[baz].Argument[block].ReturnValue.Method[instanceMethodInSubclass].Parameter[block].Argument[0]
end
def self.singletonMethodInSubclass
yield "bar" # $ sink=Member[Something].Method[baz].Argument[block].ReturnValue.Method[singletonMethodInSubclass].Parameter[block].Argument[0]
end
end
Something.foo { ClassWithCallbacks.new }
Something.bar { ClassWithCallbacks }
class ClassWithCallMethod
def call x
x # $ reachableFromSource=Method[topLevelMethod].Argument[0].Parameter[0]
"bar" # $ sink=Method[topLevelMethod].Argument[0].ReturnValue
end
end
topLevelMethod ClassWithCallMethod.new
blah = topLevelMethod
blah # $ reachableFromSource=Method[topLevelMethod].ReturnValue

View File

@@ -0,0 +1,10 @@
module SelfDotClass
module Mixin
def foo
self.class.bar # $ call=Member[Foo].Method[bar]
end
end
class Subclass < Foo
include Mixin
end
end

View File

@@ -1,34 +1,34 @@
MyModule #$ use=getMember("MyModule")
print MyModule.foo #$ use=getMember("MyModule").getMethod("foo").getReturn()
Kernel.print(e) #$ use=getMember("Kernel").getMethod("print").getReturn() def=getMember("Kernel").getMethod("print").getParameter(0)
Object::Kernel #$ use=getMember("Kernel")
Object::Kernel.print(e) #$ use=getMember("Kernel").getMethod("print").getReturn()
MyModule #$ source=Member[MyModule]
print MyModule.foo #$ source=Member[MyModule].Method[foo].ReturnValue
Kernel.print(e) #$ source=Member[Kernel].Method[print].ReturnValue sink=Member[Kernel].Method[print].Argument[0]
Object::Kernel #$ source=Member[Kernel]
Object::Kernel.print(e) #$ source=Member[Kernel].Method[print].ReturnValue
begin
print MyModule.bar #$ use=getMember("MyModule").getMethod("bar").getReturn()
raise AttributeError #$ use=getMember("AttributeError")
rescue AttributeError => e #$ use=getMember("AttributeError")
Kernel.print(e) #$ use=getMember("Kernel").getMethod("print").getReturn()
print MyModule.bar #$ source=Member[MyModule].Method[bar].ReturnValue
raise AttributeError #$ source=Member[AttributeError]
rescue AttributeError => e #$ source=Member[AttributeError]
Kernel.print(e) #$ source=Member[Kernel].Method[print].ReturnValue
end
Unknown.new.run #$ use=getMember("Unknown").getMethod("new").getReturn().getMethod("run").getReturn()
Foo::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz")
Unknown.new.run #$ source=Member[Unknown].Method[new].ReturnValue.Method[run].ReturnValue
Foo::Bar::Baz #$ source=Member[Foo].Member[Bar].Member[Baz]
Const = [1, 2, 3] #$ use=getMember("Array").getMethod("[]").getReturn()
Const.each do |c| #$ use=getMember("Const")
puts c #$ use=getMember("Const").getMethod("each").getBlock().getParameter(0) use=getMember("Const").getContent(element)
end #$ use=getMember("Const").getMethod("each").getReturn() def=getMember("Const").getMethod("each").getBlock()
Const = [1, 2, 3] #$ source=Member[Array].MethodBracket.ReturnValue
Const.each do |c| #$ source=Member[Const]
puts c #$ reachableFromSource=Member[Const].Method[each].Argument[block].Parameter[0] reachableFromSource=Member[Const].Element[any]
end #$ source=Member[Const].Method[each].ReturnValue sink=Member[Const].Method[each].Argument[block]
foo = Foo #$ use=getMember("Foo")
foo::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz")
foo = Foo #$ source=Member[Foo]
foo::Bar::Baz #$ source=Member[Foo].Member[Bar].Member[Baz]
FooAlias = Foo #$ use=getMember("Foo")
FooAlias::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz")
FooAlias = Foo #$ source=Member[Foo]
FooAlias::Bar::Baz #$ source=Member[Foo].Member[Bar].Member[Baz] source=Member[FooAlias].Member[Bar].Member[Baz]
module Outer
module Inner
end
end
Outer::Inner.foo #$ use=getMember("Outer").getMember("Inner").getMethod("foo").getReturn()
Outer::Inner.foo #$ source=Member[Outer].Member[Inner].Method[foo].ReturnValue
module M1
class C1
@@ -40,36 +40,36 @@ module M1
end
end
class C2 < M1::C1 #$ use=getMember("M1").getMember("C1")
class C2 < M1::C1 #$ source=Member[M1].Member[C1]
end
module M2
class C3 < M1::C1 #$ use=getMember("M1").getMember("C1")
class C3 < M1::C1 #$ source=Member[M1].Member[C1]
end
class C4 < C2 #$ use=getMember("C2")
class C4 < C2 #$ source=Member[C2]
end
end
C2 #$ use=getMember("C2") use=getMember("M1").getMember("C1").getASubclass()
M2::C3 #$ use=getMember("M2").getMember("C3") use=getMember("M1").getMember("C1").getASubclass()
M2::C4 #$ use=getMember("M2").getMember("C4") use=getMember("C2").getASubclass() use=getMember("M1").getMember("C1").getASubclass().getASubclass()
C2 #$ source=Member[C2] reachableFromSource=Member[M1].Member[C1]
M2::C3 #$ source=Member[M2].Member[C3] reachableFromSource=Member[M1].Member[C1]
M2::C4 #$ source=Member[M2].Member[C4] reachableFromSource=Member[C2] reachableFromSource=Member[M1].Member[C1]
M1::C1.m #$ use=getMember("M1").getMember("C1").getMethod("m").getReturn()
M2::C3.m #$ use=getMember("M2").getMember("C3").getMethod("m").getReturn() use=getMember("M1").getMember("C1").getASubclass().getMethod("m").getReturn()
M1::C1.m #$ source=Member[M1].Member[C1].Method[m].ReturnValue
M2::C3.m #$ source=Member[M2].Member[C3].Method[m].ReturnValue source=Member[M1].Member[C1].Method[m].ReturnValue
M1::C1.new.m #$ use=getMember("M1").getMember("C1").getMethod("new").getReturn().getMethod("m").getReturn()
M2::C3.new.m #$ use=getMember("M2").getMember("C3").getMethod("new").getReturn().getMethod("m").getReturn()
M1::C1.new.m #$ source=Member[M1].Member[C1].Method[new].ReturnValue.Method[m].ReturnValue
M2::C3.new.m #$ source=Member[M2].Member[C3].Method[new].ReturnValue.Method[m].ReturnValue
Foo.foo(a,b:c) #$ use=getMember("Foo").getMethod("foo").getReturn() def=getMember("Foo").getMethod("foo").getParameter(0) def=getMember("Foo").getMethod("foo").getKeywordParameter("b")
Foo.foo(a,b:c) #$ source=Member[Foo].Method[foo].ReturnValue sink=Member[Foo].Method[foo].Argument[0] sink=Member[Foo].Method[foo].Argument[b:]
def userDefinedFunction(x, y)
x.noApiGraph(y)
x.customEntryPointCall(y) #$ call=entryPoint("CustomEntryPointCall") use=entryPoint("CustomEntryPointCall").getReturn() rhs=entryPoint("CustomEntryPointCall").getParameter(0)
x.customEntryPointUse(y) #$ use=entryPoint("CustomEntryPointUse")
x.customEntryPointCall(y) #$ call=EntryPoint[CustomEntryPointCall] source=EntryPoint[CustomEntryPointCall].ReturnValue sink=EntryPoint[CustomEntryPointCall].Parameter[0]
x.customEntryPointUse(y) #$ source=EntryPoint[CustomEntryPointUse]
end
array = [A::B::C] #$ use=getMember("Array").getMethod("[]").getReturn()
array[0].m #$ use=getMember("A").getMember("B").getMember("C").getMethod("m").getReturn()
array = [A::B::C] #$ source=Member[Array].MethodBracket.ReturnValue
array[0].m #$ source=Member[A].Member[B].Member[C].Method[m].ReturnValue source=Member[Array].MethodBracket.ReturnValue.Element[0].Method[m].ReturnValue
A::B::C[0] #$ use=getMember("A").getMember("B").getMember("C").getContent(element_0)
A::B::C[0] #$ source=Member[A].Member[B].Member[C].Element[0]

View File

@@ -1,88 +0,0 @@
import codeql.ruby.AST
import codeql.ruby.DataFlow
import TestUtilities.InlineExpectationsTest
import codeql.ruby.ApiGraphs
class CustomEntryPointCall extends API::EntryPoint {
CustomEntryPointCall() { this = "CustomEntryPointCall" }
override DataFlow::CallNode getACall() { result.getMethodName() = "customEntryPointCall" }
}
class CustomEntryPointUse extends API::EntryPoint {
CustomEntryPointUse() { this = "CustomEntryPointUse" }
override DataFlow::LocalSourceNode getASource() {
result.(DataFlow::CallNode).getMethodName() = "customEntryPointUse"
}
}
class ApiUseTest extends InlineExpectationsTest {
ApiUseTest() { this = "ApiUseTest" }
override string getARelevantTag() { result = ["use", "def", "call"] }
private predicate relevantNode(API::Node a, DataFlow::Node n, Location l, string tag) {
l = n.getLocation() and
(
tag = "use" and
n = a.getAValueReachableFromSource()
or
tag = "def" and
n = a.asSink()
or
tag = "call" and
n = a.(API::MethodAccessNode).getCallNode()
)
}
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "use" and // def tags are always optional
exists(DataFlow::Node n | this.relevantNode(_, n, location, tag) |
// Only report the longest path on this line:
value =
max(API::Node a2, Location l2, DataFlow::Node n2 |
this.relevantNode(a2, n2, l2, tag) and
l2.getFile() = location.getFile() and
l2.getEndLine() = location.getEndLine()
|
a2.getPath()
order by
size(n2.asExpr().getExpr()), a2.getPath().length() desc, a2.getPath() desc
) and
element = n.toString()
)
}
// We also permit optional annotations for any other path on the line.
// This is used to test subclass paths, which typically have a shorter canonical path.
override predicate hasOptionalResult(Location location, string element, string tag, string value) {
exists(API::Node a, DataFlow::Node n | this.relevantNode(a, n, location, tag) |
element = n.toString() and
value = getAPath(a, _)
)
}
}
private int size(AstNode n) { not n instanceof StmtSequence and result = count(n.getAChild*()) }
/**
* Gets a path of the given `length` from the root to the given node.
* This is a copy of `API::getAPath()` without the restriction on path length,
* which would otherwise rule out paths involving `getASubclass()`.
*/
string getAPath(API::Node node, int length) {
node instanceof API::Root and
length = 0 and
result = ""
or
exists(API::Node pred, API::Label::ApiLabel lbl, string predpath |
pred.getASuccessor(lbl) = node and
predpath = getAPath(pred, length - 1) and
exists(string dot | if length = 1 then dot = "" else dot = "." |
result = predpath + dot + lbl and
// avoid producing strings longer than 1MB
result.length() < 1000 * 1000
)
)
}

View File

@@ -4,8 +4,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import DefaultFlowTest
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
where conf.hasFlowPath(source, sink)
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -506,8 +506,19 @@ def m56
a = [0, 1, 2, source(56)]
b = a.filter_map do |x|
sink(x) # $ hasValueFlow=56
x
end
sink(b[0]) # $ hasValueFlow=56
sink(b[3]) # $ hasValueFlow=56
c = a.filter_map do |x|
"safe"
end
sink(c[0]) # safe
d = ["safe"].filter_map do |x|
source(56.1)
end
sink(d[0]) # $ hasValueFlow=56.1
end
def m57
@@ -1629,4 +1640,4 @@ def m137
sink(a[10001]) # $ hasValueFlow=137.1 $ hasValueFlow=137.2 $ hasValueFlow=137.3 $ hasValueFlow=137.4
# unknown read
sink(a[1.0]) # $ hasValueFlow=137.1 $ hasValueFlow=137.2 $ hasValueFlow=137.3 $ hasValueFlow=137.4
end
end

View File

@@ -1,3 +1,5 @@
failures
testFailures
| array_flow.rb:107:10:107:13 | ...[...] | Unexpected result: hasValueFlow=11.2 |
| array_flow.rb:179:28:179:46 | # $ hasValueFlow=19 | Missing result:hasValueFlow=19 |
| array_flow.rb:180:28:180:46 | # $ hasValueFlow=19 | Missing result:hasValueFlow=19 |
@@ -25,138 +27,138 @@
| array_flow.rb:490:10:490:13 | ...[...] | Unexpected result: hasValueFlow=54.5 |
| array_flow.rb:494:10:494:13 | ...[...] | Unexpected result: hasValueFlow=54.2 |
| array_flow.rb:494:10:494:13 | ...[...] | Unexpected result: hasValueFlow=54.3 |
| array_flow.rb:575:16:575:34 | # $ hasValueFlow=63 | Missing result:hasValueFlow=63 |
| array_flow.rb:580:19:580:37 | # $ hasValueFlow=64 | Missing result:hasValueFlow=64 |
| array_flow.rb:582:16:582:34 | # $ hasValueFlow=64 | Missing result:hasValueFlow=64 |
| array_flow.rb:583:19:583:47 | # $ SPURIOUS: hasValueFlow=64 | Fixed spurious result:hasValueFlow=64 |
| array_flow.rb:584:16:584:34 | # $ hasValueFlow=64 | Missing result:hasValueFlow=64 |
| array_flow.rb:585:19:585:47 | # $ SPURIOUS: hasValueFlow=64 | Fixed spurious result:hasValueFlow=64 |
| array_flow.rb:646:10:646:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:646:10:646:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:646:10:646:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:647:10:647:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:647:10:647:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:648:10:648:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:648:10:648:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:649:10:649:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:649:10:649:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:649:10:649:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:650:10:650:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:650:10:650:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:651:10:651:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:651:10:651:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:651:10:651:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:652:10:652:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:652:10:652:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:653:10:653:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:653:10:653:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:654:10:654:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:654:10:654:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:654:10:654:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:655:10:655:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:655:10:655:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:708:14:708:14 | x | Unexpected result: hasValueFlow=76.2 |
| array_flow.rb:860:18:860:36 | # $ hasValueFlow=87 | Missing result:hasValueFlow=87 |
| array_flow.rb:861:18:861:36 | # $ hasValueFlow=87 | Missing result:hasValueFlow=87 |
| array_flow.rb:915:10:915:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:915:10:915:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:916:10:916:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:916:10:916:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:917:10:917:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:918:10:918:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:918:10:918:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:919:10:919:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:919:10:919:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:920:10:920:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:928:18:928:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.1 |
| array_flow.rb:928:18:928:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.2 |
| array_flow.rb:928:18:928:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.3 |
| array_flow.rb:929:18:929:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.1 |
| array_flow.rb:929:18:929:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.2 |
| array_flow.rb:929:18:929:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.3 |
| array_flow.rb:946:28:946:46 | # $ hasValueFlow=93 | Missing result:hasValueFlow=93 |
| array_flow.rb:947:28:947:46 | # $ hasValueFlow=93 | Missing result:hasValueFlow=93 |
| array_flow.rb:1007:16:1007:36 | # $ hasValueFlow=99.2 | Missing result:hasValueFlow=99.2 |
| array_flow.rb:1086:10:1086:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1086:10:1086:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1087:10:1087:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1088:10:1088:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1089:10:1089:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1089:10:1089:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1090:10:1090:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1090:10:1090:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1091:10:1091:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1092:10:1092:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1093:10:1093:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1093:10:1093:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:586:16:586:34 | # $ hasValueFlow=63 | Missing result:hasValueFlow=63 |
| array_flow.rb:591:19:591:37 | # $ hasValueFlow=64 | Missing result:hasValueFlow=64 |
| array_flow.rb:593:16:593:34 | # $ hasValueFlow=64 | Missing result:hasValueFlow=64 |
| array_flow.rb:594:19:594:47 | # $ SPURIOUS: hasValueFlow=64 | Fixed spurious result:hasValueFlow=64 |
| array_flow.rb:595:16:595:34 | # $ hasValueFlow=64 | Missing result:hasValueFlow=64 |
| array_flow.rb:596:19:596:47 | # $ SPURIOUS: hasValueFlow=64 | Fixed spurious result:hasValueFlow=64 |
| array_flow.rb:657:10:657:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:657:10:657:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:657:10:657:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:658:10:658:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:658:10:658:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:659:10:659:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:659:10:659:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:660:10:660:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:660:10:660:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:660:10:660:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:661:10:661:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:661:10:661:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:662:10:662:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:662:10:662:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:662:10:662:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:663:10:663:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:663:10:663:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:664:10:664:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:664:10:664:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:665:10:665:13 | ...[...] | Unexpected result: hasValueFlow=70.1 |
| array_flow.rb:665:10:665:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:665:10:665:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:666:10:666:13 | ...[...] | Unexpected result: hasValueFlow=70.2 |
| array_flow.rb:666:10:666:13 | ...[...] | Unexpected result: hasValueFlow=70.3 |
| array_flow.rb:719:14:719:14 | x | Unexpected result: hasValueFlow=76.2 |
| array_flow.rb:871:18:871:36 | # $ hasValueFlow=87 | Missing result:hasValueFlow=87 |
| array_flow.rb:872:18:872:36 | # $ hasValueFlow=87 | Missing result:hasValueFlow=87 |
| array_flow.rb:926:10:926:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:926:10:926:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:927:10:927:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:927:10:927:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:928:10:928:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:929:10:929:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:929:10:929:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:930:10:930:13 | ...[...] | Unexpected result: hasValueFlow=90.1 |
| array_flow.rb:930:10:930:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:931:10:931:13 | ...[...] | Unexpected result: hasValueFlow=90.2 |
| array_flow.rb:939:18:939:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.1 |
| array_flow.rb:939:18:939:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.2 |
| array_flow.rb:939:18:939:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.3 |
| array_flow.rb:940:18:940:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.1 |
| array_flow.rb:940:18:940:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.2 |
| array_flow.rb:940:18:940:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.3 |
| array_flow.rb:957:28:957:46 | # $ hasValueFlow=93 | Missing result:hasValueFlow=93 |
| array_flow.rb:958:28:958:46 | # $ hasValueFlow=93 | Missing result:hasValueFlow=93 |
| array_flow.rb:1018:16:1018:36 | # $ hasValueFlow=99.2 | Missing result:hasValueFlow=99.2 |
| array_flow.rb:1097:10:1097:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1097:10:1097:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1098:10:1098:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1098:10:1098:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1099:10:1099:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1099:10:1099:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1100:10:1100:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1100:10:1100:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1101:10:1101:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1101:10:1101:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1102:10:1102:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1102:10:1102:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1103:10:1103:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1103:10:1103:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1104:10:1104:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1104:10:1104:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1150:10:1150:10 | b | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1151:10:1151:13 | ...[...] | Unexpected result: hasValueFlow=108.1 |
| array_flow.rb:1151:10:1151:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1153:10:1153:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1157:10:1157:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1159:10:1159:13 | ...[...] | Unexpected result: hasValueFlow=108.1 |
| array_flow.rb:1161:10:1161:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1212:10:1212:13 | ...[...] | Unexpected result: hasValueFlow=111.1 |
| array_flow.rb:1221:10:1221:13 | ...[...] | Unexpected result: hasValueFlow=111.1 |
| array_flow.rb:1226:10:1226:13 | ...[...] | Unexpected result: hasValueFlow=111.1 |
| array_flow.rb:1250:10:1250:10 | b | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1253:10:1253:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1253:10:1253:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1274:10:1274:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1276:10:1276:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1280:10:1280:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1108:10:1108:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1109:10:1109:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1110:10:1110:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1110:10:1110:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1111:10:1111:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1111:10:1111:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1112:10:1112:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1113:10:1113:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1114:10:1114:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1114:10:1114:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1115:10:1115:13 | ...[...] | Unexpected result: hasValueFlow=105.2 |
| array_flow.rb:1115:10:1115:13 | ...[...] | Unexpected result: hasValueFlow=105.3 |
| array_flow.rb:1161:10:1161:10 | b | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1162:10:1162:13 | ...[...] | Unexpected result: hasValueFlow=108.1 |
| array_flow.rb:1162:10:1162:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1164:10:1164:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1168:10:1168:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1170:10:1170:13 | ...[...] | Unexpected result: hasValueFlow=108.1 |
| array_flow.rb:1172:10:1172:13 | ...[...] | Unexpected result: hasValueFlow=108.2 |
| array_flow.rb:1223:10:1223:13 | ...[...] | Unexpected result: hasValueFlow=111.1 |
| array_flow.rb:1232:10:1232:13 | ...[...] | Unexpected result: hasValueFlow=111.1 |
| array_flow.rb:1237:10:1237:13 | ...[...] | Unexpected result: hasValueFlow=111.1 |
| array_flow.rb:1261:10:1261:10 | b | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1264:10:1264:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1264:10:1264:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1285:10:1285:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1287:10:1287:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1291:10:1291:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1296:10:1296:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1298:10:1298:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1330:10:1330:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1334:10:1334:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1437:10:1437:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1438:10:1438:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1439:10:1439:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1440:10:1440:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1442:10:1442:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1443:10:1443:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1444:10:1444:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1445:10:1445:13 | ...[...] | Unexpected result: hasValueFlow=121.2 |
| array_flow.rb:1445:10:1445:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1446:10:1446:13 | ...[...] | Unexpected result: hasValueFlow=121.2 |
| array_flow.rb:1446:10:1446:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1302:10:1302:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1307:10:1307:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1309:10:1309:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1341:10:1341:13 | ...[...] | Unexpected result: hasValueFlow=112.2 |
| array_flow.rb:1345:10:1345:13 | ...[...] | Unexpected result: hasValueFlow=112.1 |
| array_flow.rb:1448:10:1448:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1449:10:1449:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1450:10:1450:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1451:10:1451:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1452:10:1452:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1500:18:1500:39 | # $ hasValueFlow=128.1 | Missing result:hasValueFlow=128.1 |
| array_flow.rb:1501:18:1501:39 | # $ hasValueFlow=128.2 | Missing result:hasValueFlow=128.2 |
| array_flow.rb:1502:18:1502:39 | # $ hasValueFlow=128.3 | Missing result:hasValueFlow=128.3 |
| array_flow.rb:1551:10:1551:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1551:10:1551:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1552:10:1552:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1552:10:1552:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1553:10:1553:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1554:10:1554:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1554:10:1554:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1555:10:1555:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1555:10:1555:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1556:10:1556:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1589:18:1589:39 | # $ hasValueFlow=134.3 | Missing result:hasValueFlow=134.3 |
| array_flow.rb:1590:18:1590:39 | # $ hasValueFlow=134.2 | Missing result:hasValueFlow=134.2 |
| array_flow.rb:1591:18:1591:39 | # $ hasValueFlow=134.1 | Missing result:hasValueFlow=134.1 |
| array_flow.rb:1611:19:1611:40 | # $ hasValueFlow=136.1 | Missing result:hasValueFlow=136.1 |
| array_flow.rb:1614:19:1614:70 | # $ hasValueFlow=136.2 $ SPURIOUS hasValueFlow=136.1 | Missing result:hasValueFlow=136.1 |
| array_flow.rb:1614:19:1614:70 | # $ hasValueFlow=136.2 $ SPURIOUS hasValueFlow=136.1 | Missing result:hasValueFlow=136.2 |
| array_flow.rb:1615:19:1615:40 | # $ hasValueFlow=136.1 | Missing result:hasValueFlow=136.1 |
| array_flow.rb:1453:10:1453:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1454:10:1454:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1455:10:1455:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1456:10:1456:13 | ...[...] | Unexpected result: hasValueFlow=121.2 |
| array_flow.rb:1456:10:1456:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1457:10:1457:13 | ...[...] | Unexpected result: hasValueFlow=121.2 |
| array_flow.rb:1457:10:1457:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1459:10:1459:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1460:10:1460:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1461:10:1461:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1462:10:1462:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1463:10:1463:13 | ...[...] | Unexpected result: hasValueFlow=121.3 |
| array_flow.rb:1511:18:1511:39 | # $ hasValueFlow=128.1 | Missing result:hasValueFlow=128.1 |
| array_flow.rb:1512:18:1512:39 | # $ hasValueFlow=128.2 | Missing result:hasValueFlow=128.2 |
| array_flow.rb:1513:18:1513:39 | # $ hasValueFlow=128.3 | Missing result:hasValueFlow=128.3 |
| array_flow.rb:1562:10:1562:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1562:10:1562:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1563:10:1563:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1563:10:1563:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1564:10:1564:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1565:10:1565:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1565:10:1565:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1566:10:1566:13 | ...[...] | Unexpected result: hasValueFlow=132.1 |
| array_flow.rb:1566:10:1566:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1567:10:1567:13 | ...[...] | Unexpected result: hasValueFlow=132.2 |
| array_flow.rb:1600:18:1600:39 | # $ hasValueFlow=134.3 | Missing result:hasValueFlow=134.3 |
| array_flow.rb:1601:18:1601:39 | # $ hasValueFlow=134.2 | Missing result:hasValueFlow=134.2 |
| array_flow.rb:1602:18:1602:39 | # $ hasValueFlow=134.1 | Missing result:hasValueFlow=134.1 |
| array_flow.rb:1622:19:1622:40 | # $ hasValueFlow=136.1 | Missing result:hasValueFlow=136.1 |
| array_flow.rb:1625:19:1625:70 | # $ hasValueFlow=136.2 $ SPURIOUS hasValueFlow=136.1 | Missing result:hasValueFlow=136.1 |
| array_flow.rb:1625:19:1625:70 | # $ hasValueFlow=136.2 $ SPURIOUS hasValueFlow=136.1 | Missing result:hasValueFlow=136.2 |
| array_flow.rb:1626:19:1626:40 | # $ hasValueFlow=136.1 | Missing result:hasValueFlow=136.1 |

View File

@@ -1,5 +1,6 @@
WARNING: Type BarrierGuard has been deprecated and may be removed in future (barrier-guards.ql:10,3-15)
failures
testFailures
oldStyleBarrierGuards
| barrier-guards.rb:3:4:3:15 | ... == ... | barrier-guards.rb:4:5:4:7 | foo | barrier-guards.rb:3:4:3:6 | foo | true |
| barrier-guards.rb:3:4:3:15 | ... == ... | barrier-guards.rb:4:5:4:7 | foo | barrier-guards.rb:3:11:3:15 | "foo" | true |

View File

@@ -24,12 +24,10 @@ query predicate controls(CfgNode condition, BasicBlock bb, SuccessorTypes::Condi
)
}
class BarrierGuardTest extends InlineExpectationsTest {
BarrierGuardTest() { this = "BarrierGuardTest" }
module BarrierGuardTest implements TestSig {
string getARelevantTag() { result = "guarded" }
override string getARelevantTag() { result = "guarded" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "guarded" and
exists(DataFlow::Node n |
newStyleBarrierGuards(n) and
@@ -39,3 +37,5 @@ class BarrierGuardTest extends InlineExpectationsTest {
)
}
}
import MakeTest<BarrierGuardTest>

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| call_sensitivity.rb:9:7:9:13 | call to taint | call_sensitivity.rb:9:6:9:14 | ( ... ) |
| call_sensitivity.rb:9:7:9:13 | call to taint | call_sensitivity.rb:9:6:9:14 | ( ... ) |

View File

@@ -5,13 +5,14 @@
import codeql.ruby.AST
import codeql.ruby.DataFlow
import TestUtilities.InlineFlowTest
import DataFlow::PathGraph
import DefaultFlowTest
import PathGraph
import codeql.ruby.dataflow.internal.DataFlowDispatch as DataFlowDispatch
query predicate mayBenefitFromCallContext = DataFlowDispatch::mayBenefitFromCallContext/2;
query predicate viableImplInCallContext = DataFlowDispatch::viableImplInCallContext/2;
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultTaintFlowConf conf
where conf.hasFlowPath(source, sink)
from TaintFlow::PathNode source, TaintFlow::PathNode sink
where TaintFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| semantics.rb:2:5:2:5 | a | semantics.rb:3:9:3:9 | a |
| semantics.rb:2:5:2:5 | a | semantics.rb:3:9:3:9 | a |

View File

@@ -5,6 +5,7 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import DefaultFlowTest
import PathGraph
private import codeql.ruby.dataflow.FlowSummary

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| captured_variables.rb:1:24:1:24 | x | captured_variables.rb:2:20:2:20 | x |
| captured_variables.rb:1:24:1:24 | x | captured_variables.rb:2:20:2:20 | x |

View File

@@ -5,8 +5,9 @@
import codeql.ruby.AST
import codeql.ruby.DataFlow
private import TestUtilities.InlineFlowTest
import DataFlow::PathGraph
import DefaultFlowTest
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultTaintFlowConf conf
where conf.hasFlowPath(source, sink)
from TaintFlow::PathNode source, TaintFlow::PathNode sink
where TaintFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,3 +1,5 @@
failures
testFailures
| captured_variables.rb:9:14:9:14 | x | Fixed missing result:hasValueFlow=1.2 |
| captured_variables.rb:16:14:16:14 | x | Fixed missing result:hasValueFlow=1.3 |
| instance_variables.rb:20:16:20:33 | # $ hasValueFlow=7 | Missing result:hasValueFlow=7 |

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| hash_flow.rb:10:5:10:8 | hash [element 0] | hash_flow.rb:30:10:30:13 | hash [element 0] |
| hash_flow.rb:10:5:10:8 | hash [element :a] | hash_flow.rb:22:10:22:13 | hash [element :a] |

View File

@@ -4,12 +4,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import ValueFlowTest<DefaultFlowConfig>
import PathGraph
class HasFlowTest extends InlineFlowTest {
override DataFlow::Configuration getTaintFlowConfig() { none() }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
where conf.hasFlowPath(source, sink)
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,3 +1,5 @@
failures
testFailures
| hash_flow.rb:65:21:65:40 | # $ hasValueFlow=3.3 | Missing result:hasValueFlow=3.3 |
| hash_flow.rb:66:21:66:49 | # $ SPURIOUS hasValueFlow=3.3 | Missing result:hasValueFlow=3.3 |
| hash_flow.rb:114:10:114:17 | ...[...] | Unexpected result: hasValueFlow=7.2 |

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| local_dataflow.rb:78:3:78:3 | z | local_dataflow.rb:89:8:89:8 | z |
| local_dataflow.rb:78:12:78:20 | call to source | local_dataflow.rb:79:13:79:13 | b |

View File

@@ -4,8 +4,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import DefaultFlowTest
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultTaintFlowConf conf
where conf.hasFlowPath(source, sink)
from TaintFlow::PathNode source, TaintFlow::PathNode sink
where TaintFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -2,9 +2,9 @@ import codeql.ruby.AST
import codeql.ruby.dataflow.internal.DataFlowPrivate
import codeql.ruby.dataflow.internal.DataFlowDispatch
query predicate ret(ReturningNode node) { any() }
query predicate ret(SourceReturnNode node) { any() }
query predicate arg(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) {
n.argumentOf(call, pos) and
not n instanceof SummaryNode
not n instanceof FlowSummaryNode
}

View File

@@ -2797,37 +2797,47 @@
| UseUseExplosion.rb:21:3686:21:3696 | else ... | UseUseExplosion.rb:21:9:21:3700 | if ... |
| UseUseExplosion.rb:21:3691:21:3696 | call to use | UseUseExplosion.rb:21:3686:21:3696 | else ... |
| UseUseExplosion.rb:24:5:25:7 | use | UseUseExplosion.rb:1:1:26:3 | C |
| file://:0:0:0:0 | [summary] read: argument position 0.any element in Hash[] | file://:0:0:0:0 | [summary] read: argument position 0.any element.element 1 or unknown in Hash[] |
| file://:0:0:0:0 | parameter position 0 of & | file://:0:0:0:0 | [summary] read: argument position 0.any element in & |
| file://:0:0:0:0 | parameter position 0 of + | file://:0:0:0:0 | [summary] read: argument position 0.any element in + |
| file://:0:0:0:0 | parameter position 0 of ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge |
| file://:0:0:0:0 | parameter position 0 of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: argument self in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter position 0 of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter position 0 of Arel.sql | file://:0:0:0:0 | [summary] to write: return (return) in Arel.sql |
| file://:0:0:0:0 | parameter position 0 of Base64.decode64() | file://:0:0:0:0 | [summary] to write: return (return) in Base64.decode64() |
| file://:0:0:0:0 | parameter position 0 of ERB.new | file://:0:0:0:0 | [summary] to write: return (return) in ERB.new |
| file://:0:0:0:0 | parameter position 0 of File.absolute_path | file://:0:0:0:0 | [summary] to write: return (return) in File.absolute_path |
| file://:0:0:0:0 | parameter position 0 of File.dirname | file://:0:0:0:0 | [summary] to write: return (return) in File.dirname |
| file://:0:0:0:0 | parameter position 0 of File.expand_path | file://:0:0:0:0 | [summary] to write: return (return) in File.expand_path |
| file://:0:0:0:0 | parameter position 0 of File.join | file://:0:0:0:0 | [summary] to write: return (return) in File.join |
| file://:0:0:0:0 | parameter position 0 of File.path | file://:0:0:0:0 | [summary] to write: return (return) in File.path |
| file://:0:0:0:0 | parameter position 0 of File.realdirpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realdirpath |
| file://:0:0:0:0 | parameter position 0 of File.realpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realpath |
| file://:0:0:0:0 | parameter position 0 of Hash[] | file://:0:0:0:0 | [summary] read: argument position 0.any element in Hash[] |
| file://:0:0:0:0 | parameter position 0 of String.try_convert | file://:0:0:0:0 | [summary] to write: return (return) in String.try_convert |
| file://:0:0:0:0 | parameter position 0 of \| | file://:0:0:0:0 | [summary] read: argument position 0.any element in \| |
| file://:0:0:0:0 | parameter position 1.. of File.join | file://:0:0:0:0 | [summary] to write: return (return) in File.join |
| file://:0:0:0:0 | parameter self of & | file://:0:0:0:0 | [summary] read: argument self.any element in & |
| file://:0:0:0:0 | parameter self of * | file://:0:0:0:0 | [summary] read: argument self.any element in * |
| file://:0:0:0:0 | parameter self of - | file://:0:0:0:0 | [summary] read: argument self.any element in - |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#<various> | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#<various> |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: argument self in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter self of ActiveSupportStringTransform | file://:0:0:0:0 | [summary] to write: return (return) in ActiveSupportStringTransform |
| file://:0:0:0:0 | parameter self of [] | file://:0:0:0:0 | [summary] to write: return (return) in [] |
| file://:0:0:0:0 | parameter self of \| | file://:0:0:0:0 | [summary] read: argument self.any element in \| |
| file://:0:0:0:0 | parameter self of each(0) | file://:0:0:0:0 | [summary] read: argument self.any element in each(0) |
| file://:0:0:0:0 | [summary param] position 0 in & | file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in & |
| file://:0:0:0:0 | [summary param] position 0 in + | file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in + |
| file://:0:0:0:0 | [summary param] position 0 in ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: ReturnValue in ActionController::Parameters#merge |
| file://:0:0:0:0 | [summary param] position 0 in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: Argument[self] in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] position 0 in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: ReturnValue in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] position 0 in Arel.sql | file://:0:0:0:0 | [summary] to write: ReturnValue in Arel.sql |
| file://:0:0:0:0 | [summary param] position 0 in Base64.decode64() | file://:0:0:0:0 | [summary] to write: ReturnValue in Base64.decode64() |
| file://:0:0:0:0 | [summary param] position 0 in ERB.new | file://:0:0:0:0 | [summary] to write: ReturnValue in ERB.new |
| file://:0:0:0:0 | [summary param] position 0 in File.absolute_path | file://:0:0:0:0 | [summary] to write: ReturnValue in File.absolute_path |
| file://:0:0:0:0 | [summary param] position 0 in File.dirname | file://:0:0:0:0 | [summary] to write: ReturnValue in File.dirname |
| file://:0:0:0:0 | [summary param] position 0 in File.expand_path | file://:0:0:0:0 | [summary] to write: ReturnValue in File.expand_path |
| file://:0:0:0:0 | [summary param] position 0 in File.join | file://:0:0:0:0 | [summary] to write: ReturnValue in File.join |
| file://:0:0:0:0 | [summary param] position 0 in File.path | file://:0:0:0:0 | [summary] to write: ReturnValue in File.path |
| file://:0:0:0:0 | [summary param] position 0 in File.realdirpath | file://:0:0:0:0 | [summary] to write: ReturnValue in File.realdirpath |
| file://:0:0:0:0 | [summary param] position 0 in File.realpath | file://:0:0:0:0 | [summary] to write: ReturnValue in File.realpath |
| file://:0:0:0:0 | [summary param] position 0 in Hash[] | file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in Hash[] |
| file://:0:0:0:0 | [summary param] position 0 in Mysql2::Client.escape() | file://:0:0:0:0 | [summary] to write: ReturnValue in Mysql2::Client.escape() |
| file://:0:0:0:0 | [summary param] position 0 in Mysql2::Client.new() | file://:0:0:0:0 | [summary] to write: ReturnValue in Mysql2::Client.new() |
| file://:0:0:0:0 | [summary param] position 0 in Net::LDAP.new | file://:0:0:0:0 | [summary] to write: ReturnValue in Net::LDAP.new |
| file://:0:0:0:0 | [summary param] position 0 in Net::LDAP::Filter | file://:0:0:0:0 | [summary] to write: ReturnValue in Net::LDAP::Filter |
| file://:0:0:0:0 | [summary param] position 0 in PG.new() | file://:0:0:0:0 | [summary] to write: ReturnValue in PG.new() |
| file://:0:0:0:0 | [summary param] position 0 in Rack::Utils.parse_query | file://:0:0:0:0 | [summary] to write: ReturnValue in Rack::Utils.parse_query |
| file://:0:0:0:0 | [summary param] position 0 in SQLite3::Database.quote() | file://:0:0:0:0 | [summary] to write: ReturnValue in SQLite3::Database.quote() |
| file://:0:0:0:0 | [summary param] position 0 in Sequel.connect | file://:0:0:0:0 | [summary] to write: ReturnValue in Sequel.connect |
| file://:0:0:0:0 | [summary param] position 0 in String.try_convert | file://:0:0:0:0 | [summary] to write: ReturnValue in String.try_convert |
| file://:0:0:0:0 | [summary param] position 0 in \| | file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in \| |
| file://:0:0:0:0 | [summary param] position 1 in Net::LDAP::Filter | file://:0:0:0:0 | [summary] to write: ReturnValue in Net::LDAP::Filter |
| file://:0:0:0:0 | [summary param] position 1.. in File.join | file://:0:0:0:0 | [summary] to write: ReturnValue in File.join |
| file://:0:0:0:0 | [summary param] self in & | file://:0:0:0:0 | [summary] read: Argument[self].Element[any] in & |
| file://:0:0:0:0 | [summary param] self in * | file://:0:0:0:0 | [summary] read: Argument[self].Element[any] in * |
| file://:0:0:0:0 | [summary param] self in - | file://:0:0:0:0 | [summary] read: Argument[self].Element[any] in - |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#<various> | file://:0:0:0:0 | [summary] to write: ReturnValue in ActionController::Parameters#<various> |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: ReturnValue in ActionController::Parameters#merge |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: Argument[self] in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: ReturnValue in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] self in ActiveSupportStringTransform | file://:0:0:0:0 | [summary] to write: ReturnValue in ActiveSupportStringTransform |
| file://:0:0:0:0 | [summary param] self in [] | file://:0:0:0:0 | [summary] to write: ReturnValue in [] |
| file://:0:0:0:0 | [summary param] self in \| | file://:0:0:0:0 | [summary] read: Argument[self].Element[any] in \| |
| file://:0:0:0:0 | [summary param] self in assoc-unknown-arg | file://:0:0:0:0 | [summary] read: Argument[self].Element[any] in assoc-unknown-arg |
| file://:0:0:0:0 | [summary param] self in each(0) | file://:0:0:0:0 | [summary] read: Argument[self].Element[any] in each(0) |
| file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in Hash[] | file://:0:0:0:0 | [summary] read: Argument[0].Element[any].Element[1] in Hash[] |
| local_dataflow.rb:1:1:7:3 | self (foo) | local_dataflow.rb:3:8:3:10 | self |
| local_dataflow.rb:1:1:7:3 | self in foo | local_dataflow.rb:1:1:7:3 | self (foo) |
| local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self |

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| params_flow.rb:9:16:9:17 | p1 | params_flow.rb:10:10:10:11 | p1 |
| params_flow.rb:9:20:9:21 | p2 | params_flow.rb:11:10:11:11 | p2 |

View File

@@ -4,12 +4,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import ValueFlowTest<DefaultFlowConfig>
import PathGraph
class HasFlowTest extends InlineFlowTest {
override DataFlow::Configuration getTaintFlowConfig() { none() }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
where conf.hasFlowPath(source, sink)
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| pathname_flow.rb:4:5:4:6 | pn | pathname_flow.rb:5:10:5:11 | pn |
| pathname_flow.rb:4:10:4:33 | call to new | pathname_flow.rb:4:5:4:6 | pn |

View File

@@ -4,8 +4,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import DefaultFlowTest
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
where conf.hasFlowPath(source, sink)
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| ssa_flow.rb:12:9:12:9 | [post] a [element 0] | ssa_flow.rb:16:10:16:10 | a [element 0] |
| ssa_flow.rb:12:9:12:9 | [post] a [element 0] | ssa_flow.rb:16:10:16:10 | a [element 0] |

View File

@@ -4,8 +4,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import DefaultFlowTest
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
where conf.hasFlowPath(source, sink)
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,4 +1,5 @@
failures
testFailures
| string_flow.rb:85:10:85:10 | a | Unexpected result: hasValueFlow=a |
| string_flow.rb:227:10:227:10 | a | Unexpected result: hasValueFlow=a |
edges

View File

@@ -4,8 +4,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import DefaultFlowTest
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
where conf.hasFlowPath(source, sink)
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| summaries.rb:1:1:1:7 | tainted | summaries.rb:2:6:2:12 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:2:6:2:12 | tainted |
@@ -44,6 +45,14 @@ edges
| summaries.rb:1:1:1:7 | tainted | summaries.rb:147:16:147:22 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:150:39:150:45 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:150:39:150:45 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:154:20:154:26 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:154:20:154:26 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:155:28:155:34 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:155:28:155:34 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:156:27:156:33 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:156:27:156:33 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:158:15:158:21 | tainted |
| summaries.rb:1:1:1:7 | tainted | summaries.rb:158:15:158:21 | tainted |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:1:1:1:7 | tainted |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:1:1:1:7 | tainted |
| summaries.rb:1:20:1:36 | call to source | summaries.rb:1:11:1:36 | call to identity |
@@ -231,6 +240,9 @@ edges
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:145:26:145:32 | tainted |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:147:16:147:22 | tainted |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:150:39:150:45 | tainted |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:154:20:154:26 | tainted |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:155:28:155:34 | tainted |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:156:27:156:33 | tainted |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:16:122:22 | [post] tainted |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:25:122:25 | [post] y |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:33:122:33 | [post] z |
@@ -474,6 +486,18 @@ nodes
| summaries.rb:147:16:147:22 | tainted | semmle.label | tainted |
| summaries.rb:150:39:150:45 | tainted | semmle.label | tainted |
| summaries.rb:150:39:150:45 | tainted | semmle.label | tainted |
| summaries.rb:154:20:154:26 | tainted | semmle.label | tainted |
| summaries.rb:154:20:154:26 | tainted | semmle.label | tainted |
| summaries.rb:155:28:155:34 | tainted | semmle.label | tainted |
| summaries.rb:155:28:155:34 | tainted | semmle.label | tainted |
| summaries.rb:156:27:156:33 | tainted | semmle.label | tainted |
| summaries.rb:156:27:156:33 | tainted | semmle.label | tainted |
| summaries.rb:158:15:158:21 | tainted | semmle.label | tainted |
| summaries.rb:158:15:158:21 | tainted | semmle.label | tainted |
| summaries.rb:163:20:163:36 | call to source | semmle.label | call to source |
| summaries.rb:163:20:163:36 | call to source | semmle.label | call to source |
| summaries.rb:166:20:166:36 | call to source | semmle.label | call to source |
| summaries.rb:166:20:166:36 | call to source | semmle.label | call to source |
subpaths
invalidSpecComponent
#select
@@ -573,6 +597,18 @@ invalidSpecComponent
| summaries.rb:147:16:147:22 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:147:16:147:22 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:150:39:150:45 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:150:39:150:45 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:150:39:150:45 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:150:39:150:45 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:154:20:154:26 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:154:20:154:26 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:154:20:154:26 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:154:20:154:26 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:155:28:155:34 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:155:28:155:34 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:155:28:155:34 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:155:28:155:34 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:156:27:156:33 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:156:27:156:33 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:156:27:156:33 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:156:27:156:33 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:158:15:158:21 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:158:15:158:21 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:158:15:158:21 | tainted | summaries.rb:1:20:1:36 | call to source | summaries.rb:158:15:158:21 | tainted | $@ | summaries.rb:1:20:1:36 | call to source | call to source |
| summaries.rb:163:20:163:36 | call to source | summaries.rb:163:20:163:36 | call to source | summaries.rb:163:20:163:36 | call to source | $@ | summaries.rb:163:20:163:36 | call to source | call to source |
| summaries.rb:163:20:163:36 | call to source | summaries.rb:163:20:163:36 | call to source | summaries.rb:163:20:163:36 | call to source | $@ | summaries.rb:163:20:163:36 | call to source | call to source |
| summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | $@ | summaries.rb:166:20:166:36 | call to source | call to source |
| summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | $@ | summaries.rb:166:20:166:36 | call to source | call to source |
warning
| CSV type row should have 3 columns but has 1: TooFewColumns |
| CSV type row should have 3 columns but has 6: TooManyColumns;;Member[Foo].Instance;too;many;columns |

View File

@@ -10,7 +10,7 @@ import codeql.ruby.dataflow.internal.FlowSummaryImpl
import codeql.ruby.dataflow.internal.AccessPathSyntax
import codeql.ruby.frameworks.data.ModelsAsData
import TestUtilities.InlineFlowTest
import DataFlow::PathGraph
import PathGraph
query predicate invalidSpecComponent(SummarizedCallable sc, string s, string c) {
(sc.propagatesFlowExt(s, _, _) or sc.propagatesFlowExt(_, s, _)) and
@@ -145,26 +145,23 @@ private class SinkFromModel extends ModelInput::SinkModelCsv {
"Foo!;Method[getSinks].ReturnValue.Element[any].Method[mySink].Argument[0];test-sink", //
"Foo!;Method[arraySink].Argument[0].Element[any];test-sink", //
"Foo!;Method[secondArrayElementIsSink].Argument[0].Element[1];test-sink", //
"FuzzyLib!;Fuzzy.Method[fuzzyCall].Argument[0];test-sink"
]
}
}
class CustomValueSink extends DefaultValueFlowConf {
override predicate isSink(DataFlow::Node sink) {
super.isSink(sink)
module CustomConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { DefaultFlowConfig::isSource(source) }
predicate isSink(DataFlow::Node sink) {
DefaultFlowConfig::isSink(sink)
or
sink = ModelOutput::getASinkNode("test-sink").asSink()
}
}
class CustomTaintSink extends DefaultTaintFlowConf {
override predicate isSink(DataFlow::Node sink) {
super.isSink(sink)
or
sink = ModelOutput::getASinkNode("test-sink").asSink()
}
}
import FlowTest<CustomConfig, CustomConfig>
from DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Configuration conf
where conf.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -150,3 +150,19 @@ Foo.secondArrayElementIsSink([tainted, "safe", "safe"])
Foo.secondArrayElementIsSink(["safe", tainted, "safe"]) # $ hasValueFlow=tainted
Foo.secondArrayElementIsSink(["safe", "safe", tainted])
Foo.secondArrayElementIsSink([tainted] * 10) # $ MISSING: hasValueFlow=tainted
FuzzyLib.fuzzyCall(tainted) # $ hasValueFlow=tainted
FuzzyLib.foo.bar.fuzzyCall(tainted) # $ hasValueFlow=tainted
FuzzyLib.foo[0].fuzzyCall(tainted) # $ hasValueFlow=tainted
FuzzyLib.foo do |x|
x.fuzzyCall(tainted) # $ hasValueFlow=tainted
x.otherCall(tainted)
end
class FuzzySub < FuzzyLib::Foo
def blah
self.fuzzyCall(source("tainted")) # $ hasValueFlow=tainted
end
def self.blah
self.fuzzyCall(source("tainted")) # $ hasValueFlow=tainted
end
end

View File

@@ -1,129 +1,72 @@
track
| type_tracker.rb:1:1:10:3 | self (Container) | type tracker without call steps | type_tracker.rb:1:1:10:3 | self (Container) |
| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type tracker with call steps | type_tracker.rb:18:1:21:3 | self (positional) |
| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type tracker with call steps | type_tracker.rb:18:1:21:3 | self in positional |
| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type tracker with call steps | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type tracker with call steps | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type tracker without call steps | type_tracker.rb:1:1:53:4 | self (type_tracker.rb) |
| type_tracker.rb:2:5:5:7 | &block | type tracker without call steps | type_tracker.rb:2:5:5:7 | &block |
| type_tracker.rb:2:5:5:7 | field= | type tracker without call steps | type_tracker.rb:2:5:5:7 | field= |
| type_tracker.rb:2:5:5:7 | return return in field= | type tracker without call steps | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:5:5:7 | return return in field= | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:5:5:7 | self (field=) | type tracker with call steps | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:2:5:5:7 | self (field=) | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:2:5:5:7 | self (field=) | type tracker without call steps | type_tracker.rb:2:5:5:7 | self (field=) |
| type_tracker.rb:2:5:5:7 | self in field= | type tracker with call steps | type_tracker.rb:2:5:5:7 | self (field=) |
| type_tracker.rb:2:5:5:7 | self in field= | type tracker with call steps | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:2:5:5:7 | self in field= | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:2:5:5:7 | self in field= | type tracker without call steps | type_tracker.rb:2:5:5:7 | self in field= |
| type_tracker.rb:2:16:2:18 | val | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type tracker with call steps | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:3:9:3:23 | call to puts | type tracker without call steps | type_tracker.rb:3:9:3:23 | call to puts |
| type_tracker.rb:3:14:3:23 | call to field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:4:9:4:14 | @field | type tracker without call steps | type_tracker.rb:4:9:4:14 | @field |
| type_tracker.rb:7:5:9:7 | &block | type tracker without call steps | type_tracker.rb:7:5:9:7 | &block |
| type_tracker.rb:7:5:9:7 | field | type tracker without call steps | type_tracker.rb:7:5:9:7 | field |
| type_tracker.rb:7:5:9:7 | return return in field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:7:5:9:7 | return return in field | type tracker without call steps | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:7:5:9:7 | return return in field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:7:5:9:7 | self (field) | type tracker without call steps | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:7:5:9:7 | self in field | type tracker with call steps | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:7:5:9:7 | self in field | type tracker without call steps | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:12:1:16:3 | &block | type tracker without call steps | type_tracker.rb:12:1:16:3 | &block |
| type_tracker.rb:12:1:16:3 | m | type tracker without call steps | type_tracker.rb:12:1:16:3 | m |
| type_tracker.rb:12:1:16:3 | return return in m | type tracker without call steps | type_tracker.rb:12:1:16:3 | return return in m |
| type_tracker.rb:12:1:16:3 | self (m) | type tracker without call steps | type_tracker.rb:12:1:16:3 | self (m) |
| type_tracker.rb:12:1:16:3 | self in m | type tracker with call steps | type_tracker.rb:12:1:16:3 | self (m) |
| type_tracker.rb:12:1:16:3 | self in m | type tracker without call steps | type_tracker.rb:12:1:16:3 | self in m |
| type_tracker.rb:13:5:13:7 | var | type tracker without call steps | type_tracker.rb:13:5:13:7 | var |
| type_tracker.rb:13:11:13:19 | Container | type tracker without call steps | type_tracker.rb:13:11:13:19 | Container |
| type_tracker.rb:13:11:13:23 | call to new | type tracker with call steps | type_tracker.rb:2:5:5:7 | self (field=) |
| type_tracker.rb:13:11:13:23 | call to new | type tracker with call steps | type_tracker.rb:2:5:5:7 | self in field= |
| type_tracker.rb:13:11:13:23 | call to new | type tracker with call steps | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:13:11:13:23 | call to new | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:13:11:13:23 | call to new | type tracker without call steps | type_tracker.rb:13:11:13:23 | call to new |
| type_tracker.rb:14:5:14:7 | [post] var | type tracker with call steps | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:14:5:14:7 | [post] var | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:14:5:14:7 | [post] var | type tracker without call steps | type_tracker.rb:14:5:14:7 | [post] var |
| type_tracker.rb:14:5:14:13 | call to field= | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps with content attribute field | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps with content attribute field | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:14:17:14:23 | "hello" |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps with content attribute field | type_tracker.rb:14:5:14:7 | [post] var |
| type_tracker.rb:14:17:14:23 | __synth__0 | type tracker without call steps | type_tracker.rb:14:17:14:23 | __synth__0 |
| type_tracker.rb:15:5:15:18 | call to puts | type tracker without call steps | type_tracker.rb:12:1:16:3 | return return in m |
| type_tracker.rb:15:5:15:18 | call to puts | type tracker without call steps | type_tracker.rb:15:5:15:18 | call to puts |
| type_tracker.rb:15:10:15:18 | call to field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:18:1:21:3 | &block | type tracker without call steps | type_tracker.rb:18:1:21:3 | &block |
| type_tracker.rb:18:1:21:3 | positional | type tracker without call steps | type_tracker.rb:18:1:21:3 | positional |
| type_tracker.rb:18:1:21:3 | return return in positional | type tracker without call steps | type_tracker.rb:18:1:21:3 | return return in positional |
| type_tracker.rb:18:1:21:3 | return return in positional | type tracker without call steps | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:18:1:21:3 | self (positional) | type tracker without call steps | type_tracker.rb:18:1:21:3 | self (positional) |
| type_tracker.rb:18:1:21:3 | self in positional | type tracker with call steps | type_tracker.rb:18:1:21:3 | self (positional) |
| type_tracker.rb:18:1:21:3 | self in positional | type tracker without call steps | type_tracker.rb:18:1:21:3 | self in positional |
| type_tracker.rb:18:16:18:17 | p1 | type tracker with call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type tracker without call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type tracker without call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type tracker without call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:20:18:21 | p2 | type tracker with call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type tracker without call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type tracker without call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type tracker without call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:19:5:19:11 | call to puts | type tracker without call steps | type_tracker.rb:19:5:19:11 | call to puts |
| type_tracker.rb:20:5:20:11 | call to puts | type tracker without call steps | type_tracker.rb:18:1:21:3 | return return in positional |
| type_tracker.rb:20:5:20:11 | call to puts | type tracker without call steps | type_tracker.rb:20:5:20:11 | call to puts |
| type_tracker.rb:20:5:20:11 | call to puts | type tracker without call steps | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:23:1:23:16 | call to positional | type tracker without call steps | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:23:12:23:12 | 1 | type tracker with call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:23:12:23:12 | 1 | type tracker with call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:23:12:23:12 | 1 | type tracker without call steps | type_tracker.rb:23:12:23:12 | 1 |
| type_tracker.rb:23:15:23:15 | 2 | type tracker with call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:23:15:23:15 | 2 | type tracker with call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:23:15:23:15 | 2 | type tracker without call steps | type_tracker.rb:23:15:23:15 | 2 |
| type_tracker.rb:25:1:28:3 | &block | type tracker without call steps | type_tracker.rb:25:1:28:3 | &block |
| type_tracker.rb:25:1:28:3 | **kwargs | type tracker without call steps | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:25:1:28:3 | keyword | type tracker without call steps | type_tracker.rb:25:1:28:3 | keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type tracker without call steps | type_tracker.rb:25:1:28:3 | return return in keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type tracker without call steps | type_tracker.rb:30:1:30:21 | call to keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type tracker without call steps | type_tracker.rb:31:1:31:21 | call to keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type tracker without call steps | type_tracker.rb:32:1:32:27 | call to keyword |
| type_tracker.rb:25:1:28:3 | self (keyword) | type tracker without call steps | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:25:1:28:3 | self in keyword | type tracker with call steps | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:25:1:28:3 | self in keyword | type tracker without call steps | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:25:13:25:14 | p1 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type tracker without call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type tracker without call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type tracker without call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:18:25:19 | p2 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type tracker without call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type tracker without call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type tracker without call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:26:5:26:11 | call to puts | type tracker without call steps | type_tracker.rb:26:5:26:11 | call to puts |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:25:1:28:3 | return return in keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:27:5:27:11 | call to puts |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:30:1:30:21 | call to keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:31:1:31:21 | call to keyword |
@@ -134,14 +77,12 @@ track
| type_tracker.rb:30:9:30:10 | :p1 | type tracker without call steps | type_tracker.rb:30:9:30:10 | :p1 |
| type_tracker.rb:30:9:30:13 | Pair | type tracker without call steps | type_tracker.rb:30:9:30:13 | Pair |
| type_tracker.rb:30:13:30:13 | 3 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:30:13:30:13 | 3 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:30:13:30:13 | 3 | type tracker with call steps with content element :p1 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:30:13:30:13 | 3 | type tracker without call steps | type_tracker.rb:30:13:30:13 | 3 |
| type_tracker.rb:30:13:30:13 | 3 | type tracker without call steps with content element :p1 | type_tracker.rb:30:1:30:21 | ** |
| type_tracker.rb:30:16:30:17 | :p2 | type tracker without call steps | type_tracker.rb:30:16:30:17 | :p2 |
| type_tracker.rb:30:16:30:20 | Pair | type tracker without call steps | type_tracker.rb:30:16:30:20 | Pair |
| type_tracker.rb:30:20:30:20 | 4 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:30:20:30:20 | 4 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:30:20:30:20 | 4 | type tracker with call steps with content element :p2 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:30:20:30:20 | 4 | type tracker without call steps | type_tracker.rb:30:20:30:20 | 4 |
| type_tracker.rb:30:20:30:20 | 4 | type tracker without call steps with content element :p2 | type_tracker.rb:30:1:30:21 | ** |
@@ -151,14 +92,12 @@ track
| type_tracker.rb:31:9:31:10 | :p2 | type tracker without call steps | type_tracker.rb:31:9:31:10 | :p2 |
| type_tracker.rb:31:9:31:13 | Pair | type tracker without call steps | type_tracker.rb:31:9:31:13 | Pair |
| type_tracker.rb:31:13:31:13 | 5 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:31:13:31:13 | 5 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:31:13:31:13 | 5 | type tracker with call steps with content element :p2 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:31:13:31:13 | 5 | type tracker without call steps | type_tracker.rb:31:13:31:13 | 5 |
| type_tracker.rb:31:13:31:13 | 5 | type tracker without call steps with content element :p2 | type_tracker.rb:31:1:31:21 | ** |
| type_tracker.rb:31:16:31:17 | :p1 | type tracker without call steps | type_tracker.rb:31:16:31:17 | :p1 |
| type_tracker.rb:31:16:31:20 | Pair | type tracker without call steps | type_tracker.rb:31:16:31:20 | Pair |
| type_tracker.rb:31:20:31:20 | 6 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:31:20:31:20 | 6 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:31:20:31:20 | 6 | type tracker with call steps with content element :p1 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:31:20:31:20 | 6 | type tracker without call steps | type_tracker.rb:31:20:31:20 | 6 |
| type_tracker.rb:31:20:31:20 | 6 | type tracker without call steps with content element :p1 | type_tracker.rb:31:1:31:21 | ** |
@@ -168,68 +107,33 @@ track
| type_tracker.rb:32:9:32:11 | :p2 | type tracker without call steps | type_tracker.rb:32:9:32:11 | :p2 |
| type_tracker.rb:32:9:32:16 | Pair | type tracker without call steps | type_tracker.rb:32:9:32:16 | Pair |
| type_tracker.rb:32:16:32:16 | 7 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:32:16:32:16 | 7 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:32:16:32:16 | 7 | type tracker with call steps with content element :p2 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:32:16:32:16 | 7 | type tracker without call steps | type_tracker.rb:32:16:32:16 | 7 |
| type_tracker.rb:32:16:32:16 | 7 | type tracker without call steps with content element :p2 | type_tracker.rb:32:1:32:27 | ** |
| type_tracker.rb:32:19:32:21 | :p1 | type tracker without call steps | type_tracker.rb:32:19:32:21 | :p1 |
| type_tracker.rb:32:19:32:26 | Pair | type tracker without call steps | type_tracker.rb:32:19:32:26 | Pair |
| type_tracker.rb:32:26:32:26 | 8 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:32:26:32:26 | 8 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:32:26:32:26 | 8 | type tracker with call steps with content element :p1 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:32:26:32:26 | 8 | type tracker without call steps | type_tracker.rb:32:26:32:26 | 8 |
| type_tracker.rb:32:26:32:26 | 8 | type tracker without call steps with content element :p1 | type_tracker.rb:32:1:32:27 | ** |
| type_tracker.rb:34:1:53:3 | &block | type tracker without call steps | type_tracker.rb:34:1:53:3 | &block |
| type_tracker.rb:34:1:53:3 | return return in throughArray | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:1:53:3 | self in throughArray | type tracker without call steps | type_tracker.rb:34:1:53:3 | self in throughArray |
| type_tracker.rb:34:1:53:3 | throughArray | type tracker without call steps | type_tracker.rb:34:1:53:3 | throughArray |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps | type_tracker.rb:36:5:36:10 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps with content element | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps with content element | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps with content element 0 or unknown | type_tracker.rb:35:11:35:15 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps with content element 0 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker with call steps with content element 0 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:36:5:36:10 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:36:5:36:10 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:35:11:35:15 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:35:11:35:15 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:34:23:34:23 | y | type tracker with call steps | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:26:34:26 | z | type tracker with call steps | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type tracker without call steps | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type tracker without call steps | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type tracker without call steps | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:35:5:35:7 | tmp | type tracker without call steps | type_tracker.rb:35:5:35:7 | tmp |
@@ -315,46 +219,33 @@ track
| type_tracker.rb:50:5:50:10 | array4 | type tracker without call steps | type_tracker.rb:50:5:50:10 | array4 |
| type_tracker.rb:50:14:50:26 | Array | type tracker without call steps | type_tracker.rb:50:14:50:26 | Array |
| type_tracker.rb:50:14:50:26 | call to [] | type tracker without call steps | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps | type_tracker.rb:50:15:50:15 | 1 |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps with content element 0 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps | type_tracker.rb:50:17:50:17 | 2 |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps with content element 1 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps | type_tracker.rb:50:19:50:19 | 3 |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps with content element 2 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps | type_tracker.rb:50:21:50:21 | 4 |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps with content element 3 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps | type_tracker.rb:50:23:50:23 | 5 |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps with content element 4 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps | type_tracker.rb:50:25:50:25 | 6 |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps with content element | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps with content element 5 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:51:5:51:10 | [post] array4 | type tracker without call steps | type_tracker.rb:51:5:51:10 | [post] array4 |
| type_tracker.rb:51:5:51:13 | call to []= | type tracker without call steps | type_tracker.rb:51:5:51:13 | call to []= |
| type_tracker.rb:51:17:51:19 | __synth__0 | type tracker without call steps | type_tracker.rb:51:17:51:19 | __synth__0 |
| type_tracker.rb:52:5:52:13 | ...[...] | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:52:5:52:13 | ...[...] | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
trackEnd
| type_tracker.rb:1:1:10:3 | self (Container) | type_tracker.rb:1:1:10:3 | self (Container) |
@@ -373,15 +264,6 @@ trackEnd
| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:32:1:32:27 | self |
| type_tracker.rb:2:5:5:7 | &block | type_tracker.rb:2:5:5:7 | &block |
| type_tracker.rb:2:5:5:7 | field= | type_tracker.rb:2:5:5:7 | field= |
| type_tracker.rb:2:5:5:7 | return return in field= | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:5:5:7 | return return in field= | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:2:5:5:7 | self (field=) |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:3:9:3:23 | self |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:3:14:3:17 | self |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:4:9:4:14 | self |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:8:9:8:14 | self |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:2:5:5:7 | self (field=) |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:2:5:5:7 | self in field= |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:3:9:3:23 | self |
@@ -390,25 +272,14 @@ trackEnd
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:8:9:8:14 | self |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:9:4:20 | ... = ... |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:9:4:20 | ... = ... |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:18:4:20 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:18:4:20 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:3:9:3:23 | call to puts | type_tracker.rb:3:9:3:23 | call to puts |
| type_tracker.rb:3:14:3:23 | call to field | type_tracker.rb:3:14:3:23 | call to field |
@@ -416,23 +287,14 @@ trackEnd
| type_tracker.rb:7:5:9:7 | &block | type_tracker.rb:7:5:9:7 | &block |
| type_tracker.rb:7:5:9:7 | field | type_tracker.rb:1:1:10:3 | Container |
| type_tracker.rb:7:5:9:7 | field | type_tracker.rb:7:5:9:7 | field |
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:7:5:9:7 | self (field) | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:7:5:9:7 | self (field) | type_tracker.rb:8:9:8:14 | self |
| type_tracker.rb:7:5:9:7 | self in field | type_tracker.rb:7:5:9:7 | self (field) |
| type_tracker.rb:7:5:9:7 | self in field | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:7:5:9:7 | self in field | type_tracker.rb:8:9:8:14 | self |
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:7:5:9:7 | return return in field |
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:12:1:16:3 | &block | type_tracker.rb:12:1:16:3 | &block |
| type_tracker.rb:12:1:16:3 | m | type_tracker.rb:12:1:16:3 | m |
| type_tracker.rb:12:1:16:3 | return return in m | type_tracker.rb:12:1:16:3 | return return in m |
| type_tracker.rb:12:1:16:3 | self (m) | type_tracker.rb:12:1:16:3 | self (m) |
| type_tracker.rb:12:1:16:3 | self (m) | type_tracker.rb:15:5:15:18 | self |
| type_tracker.rb:12:1:16:3 | self in m | type_tracker.rb:12:1:16:3 | self (m) |
| type_tracker.rb:12:1:16:3 | self in m | type_tracker.rb:12:1:16:3 | self in m |
| type_tracker.rb:12:1:16:3 | self in m | type_tracker.rb:15:5:15:18 | self |
@@ -470,16 +332,10 @@ trackEnd
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | __synth__0 |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:14:17:14:23 | __synth__0 | type_tracker.rb:14:17:14:23 | __synth__0 |
| type_tracker.rb:15:5:15:18 | call to puts | type_tracker.rb:12:1:16:3 | return return in m |
| type_tracker.rb:15:5:15:18 | call to puts | type_tracker.rb:15:5:15:18 | call to puts |
| type_tracker.rb:15:10:15:18 | call to field | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:18:1:21:3 | &block | type_tracker.rb:18:1:21:3 | &block |
| type_tracker.rb:18:1:21:3 | positional | type_tracker.rb:18:1:21:3 | positional |
| type_tracker.rb:18:1:21:3 | return return in positional | type_tracker.rb:18:1:21:3 | return return in positional |
| type_tracker.rb:18:1:21:3 | return return in positional | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:18:1:21:3 | self (positional) | type_tracker.rb:18:1:21:3 | self (positional) |
| type_tracker.rb:18:1:21:3 | self (positional) | type_tracker.rb:19:5:19:11 | self |
| type_tracker.rb:18:1:21:3 | self (positional) | type_tracker.rb:20:5:20:11 | self |
| type_tracker.rb:18:1:21:3 | self in positional | type_tracker.rb:18:1:21:3 | self (positional) |
| type_tracker.rb:18:1:21:3 | self in positional | type_tracker.rb:18:1:21:3 | self in positional |
| type_tracker.rb:18:1:21:3 | self in positional | type_tracker.rb:19:5:19:11 | self |
@@ -487,17 +343,12 @@ trackEnd
| type_tracker.rb:18:16:18:17 | p1 | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type_tracker.rb:19:10:19:11 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type_tracker.rb:19:10:19:11 | p1 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:20:10:20:11 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:20:10:20:11 | p2 |
| type_tracker.rb:19:5:19:11 | call to puts | type_tracker.rb:19:5:19:11 | call to puts |
| type_tracker.rb:20:5:20:11 | call to puts | type_tracker.rb:18:1:21:3 | return return in positional |
| type_tracker.rb:20:5:20:11 | call to puts | type_tracker.rb:20:5:20:11 | call to puts |
| type_tracker.rb:20:5:20:11 | call to puts | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:23:1:23:16 | call to positional | type_tracker.rb:23:1:23:16 | call to positional |
@@ -512,13 +363,6 @@ trackEnd
| type_tracker.rb:25:1:28:3 | &block | type_tracker.rb:25:1:28:3 | &block |
| type_tracker.rb:25:1:28:3 | **kwargs | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:25:1:28:3 | keyword | type_tracker.rb:25:1:28:3 | keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type_tracker.rb:25:1:28:3 | return return in keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type_tracker.rb:30:1:30:21 | call to keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type_tracker.rb:31:1:31:21 | call to keyword |
| type_tracker.rb:25:1:28:3 | return return in keyword | type_tracker.rb:32:1:32:27 | call to keyword |
| type_tracker.rb:25:1:28:3 | self (keyword) | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:25:1:28:3 | self (keyword) | type_tracker.rb:26:5:26:11 | self |
| type_tracker.rb:25:1:28:3 | self (keyword) | type_tracker.rb:27:5:27:11 | self |
| type_tracker.rb:25:1:28:3 | self in keyword | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:25:1:28:3 | self in keyword | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:25:1:28:3 | self in keyword | type_tracker.rb:26:5:26:11 | self |
@@ -526,17 +370,12 @@ trackEnd
| type_tracker.rb:25:13:25:14 | p1 | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type_tracker.rb:26:10:26:11 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type_tracker.rb:26:10:26:11 | p1 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:27:10:27:11 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:27:10:27:11 | p2 |
| type_tracker.rb:26:5:26:11 | call to puts | type_tracker.rb:26:5:26:11 | call to puts |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:25:1:28:3 | return return in keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:27:5:27:11 | call to puts |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:30:1:30:21 | call to keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:31:1:31:21 | call to keyword |
@@ -587,80 +426,45 @@ trackEnd
| type_tracker.rb:32:26:32:26 | 8 | type_tracker.rb:26:10:26:11 | p1 |
| type_tracker.rb:32:26:32:26 | 8 | type_tracker.rb:32:26:32:26 | 8 |
| type_tracker.rb:34:1:53:3 | &block | type_tracker.rb:34:1:53:3 | &block |
| type_tracker.rb:34:1:53:3 | return return in throughArray | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:1:53:3 | self in throughArray | type_tracker.rb:34:1:53:3 | self in throughArray |
| type_tracker.rb:34:1:53:3 | throughArray | type_tracker.rb:34:1:53:3 | throughArray |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:34:18:34:20 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:35:12:35:14 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:35:12:35:14 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:36:5:36:10 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:36:5:36:10 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:5:39:12 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:5:39:12 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:5:39:18 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:5:39:18 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:5:43:13 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:5:43:13 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:5:43:19 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:5:43:19 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:5:47:13 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:5:47:13 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:5:47:19 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:5:47:19 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:5:51:13 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:5:51:13 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:5:51:19 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:5:51:19 | ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | ... = ... |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | __synth__0 |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | obj |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:39:11:39:11 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:39:11:39:11 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:44:12:44:12 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:44:12:44:12 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:51:12:51:12 | y |
| type_tracker.rb:34:23:34:23 | y | type_tracker.rb:51:12:51:12 | y |
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:52:12:52:12 | z |
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:52:12:52:12 | z |
| type_tracker.rb:35:5:35:7 | tmp | type_tracker.rb:35:5:35:7 | tmp |
| type_tracker.rb:35:11:35:15 | Array | type_tracker.rb:35:11:35:15 | Array |
@@ -743,29 +547,22 @@ trackEnd
| type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:51:5:51:10 | array4 |
| type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:52:5:52:10 | array4 |
| type_tracker.rb:50:15:50:15 | 1 | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:15:50:15 | 1 | type_tracker.rb:50:15:50:15 | 1 |
| type_tracker.rb:50:15:50:15 | 1 | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:17:50:17 | 2 | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:17:50:17 | 2 | type_tracker.rb:50:17:50:17 | 2 |
| type_tracker.rb:50:17:50:17 | 2 | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:19:50:19 | 3 | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:19:50:19 | 3 | type_tracker.rb:50:19:50:19 | 3 |
| type_tracker.rb:50:19:50:19 | 3 | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:21:50:21 | 4 | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:21:50:21 | 4 | type_tracker.rb:50:21:50:21 | 4 |
| type_tracker.rb:50:21:50:21 | 4 | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:23:50:23 | 5 | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:23:50:23 | 5 | type_tracker.rb:50:23:50:23 | 5 |
| type_tracker.rb:50:23:50:23 | 5 | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:25:50:25 | 6 | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:50:25:50:25 | 6 | type_tracker.rb:50:25:50:25 | 6 |
| type_tracker.rb:50:25:50:25 | 6 | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:51:5:51:10 | [post] array4 | type_tracker.rb:51:5:51:10 | [post] array4 |
| type_tracker.rb:51:5:51:10 | [post] array4 | type_tracker.rb:52:5:52:10 | array4 |
| type_tracker.rb:51:5:51:13 | call to []= | type_tracker.rb:51:5:51:13 | call to []= |
| type_tracker.rb:51:17:51:19 | __synth__0 | type_tracker.rb:51:17:51:19 | __synth__0 |
| type_tracker.rb:52:5:52:13 | ...[...] | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:52:5:52:13 | ...[...] | type_tracker.rb:52:5:52:13 | ...[...] |
forwardButNoBackwardFlow
backwardButNoForwardFlow

View File

@@ -1,6 +1,8 @@
sourceTest
| hello_world_server.rb:8:13:8:15 | req |
| hello_world_server.rb:32:18:32:20 | req |
ssrfSinkTest
| hello_world_client.rb:6:47:6:75 | "http://localhost:8080/twirp" |
serviceInstantiationTest
| hello_world_server.rb:24:11:24:61 | call to new |
| hello_world_server.rb:38:1:38:57 | call to new |

View File

@@ -5,4 +5,4 @@ query predicate sourceTest(Twirp::UnmarshaledParameter source) { any() }
query predicate ssrfSinkTest(Twirp::ServiceUrlAsSsrfSink sink) { any() }
query predicate serviceInstantiationTest(Twirp::ServiceInstantiation si) { any() }
deprecated query predicate serviceInstantiationTest(Twirp::ServiceInstantiation si) { any() }

View File

@@ -5,7 +5,7 @@ require_relative 'hello_world/service_twirp.rb'
class HelloWorldHandler
# test: request
def hello(req, env)
def hello(req, env)
puts ">> Hello #{req.name}"
{message: "Hello #{req.name}"}
end
@@ -13,7 +13,7 @@ end
class FakeHelloWorldHandler
# test: !request
def hello(req, env)
def hello(req, env)
puts ">> Hello #{req.name}"
{message: "Hello #{req.name}"}
end
@@ -21,9 +21,18 @@ end
handler = HelloWorldHandler.new()
# test: serviceInstantiation
service = Example::HelloWorld::HelloWorldService.new(handler)
service = Example::HelloWorld::HelloWorldService.new(handler)
path_prefix = "/twirp/" + service.full_name
server = WEBrick::HTTPServer.new(Port: 8080)
server.mount path_prefix, Rack::Handler::WEBrick, service
server.start
class StaticHandler
def self.hello(req, env)
puts ">> Hello #{req.name}"
{message: "Hello #{req.name}"}
end
end
Example::HelloWorld::HelloWorldService.new(StaticHandler)

View File

@@ -1,4 +1,5 @@
failures
testFailures
| filter_flow.rb:21:10:21:13 | @foo | Unexpected result: hasTaintFlow= |
| filter_flow.rb:38:10:38:13 | @foo | Unexpected result: hasTaintFlow= |
| filter_flow.rb:55:10:55:13 | @foo | Unexpected result: hasTaintFlow= |

View File

@@ -7,12 +7,14 @@ import TestUtilities.InlineFlowTest
import PathGraph
import codeql.ruby.frameworks.Rails
class ParamsTaintFlowConf extends DefaultTaintFlowConf {
override predicate isSource(DataFlow::Node n) {
n.asExpr().getExpr() instanceof Rails::ParamsCall
}
module ParamsTaintFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n.asExpr().getExpr() instanceof Rails::ParamsCall }
predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ParamsTaintFlowConf conf
where conf.hasFlowPath(source, sink)
import FlowTest<DefaultFlowConfig, ParamsTaintFlowConfig>
from TaintFlow::PathNode source, TaintFlow::PathNode sink
where TaintFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -36,8 +36,8 @@ actionDispatchRoutes
actionDispatchControllerMethods
| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:2:3:3:5 | index |
| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:5:3:6:5 | show |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:2:3:36:5 | index |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:38:3:39:5 | show |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:2:3:39:5 | index |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:41:3:42:5 | show |
| app/config/routes.rb:7:5:7:37 | call to post | app/controllers/posts_controller.rb:8:3:9:5 | upvote |
| app/config/routes.rb:27:3:27:48 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show |
| app/config/routes.rb:28:3:28:50 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show |
@@ -55,14 +55,28 @@ underscore
| LotsOfCapitalLetters | lots_of_capital_letters |
| invalid | invalid |
mimeTypeInstances
| mime_type.rb:2:6:2:28 | Use getMember("Mime").getContent(element_text/html) |
| mime_type.rb:3:6:3:32 | Use getMember("Mime").getMember("Type").getMethod("new").getReturn() |
| mime_type.rb:4:6:4:35 | Use getMember("Mime").getMember("Type").getMethod("lookup").getReturn() |
| mime_type.rb:5:6:5:43 | Use getMember("Mime").getMember("Type").getMethod("lookup_by_extension").getReturn() |
| mime_type.rb:6:6:6:47 | Use getMember("Mime").getMember("Type").getMethod("register").getReturn() |
| mime_type.rb:7:6:7:64 | Use getMember("Mime").getMember("Type").getMethod("register_alias").getReturn() |
| mime_type.rb:2:6:2:28 | ForwardNode(call to fetch) |
| mime_type.rb:3:6:3:32 | ForwardNode(call to new) |
| mime_type.rb:4:6:4:35 | ForwardNode(call to lookup) |
| mime_type.rb:5:6:5:43 | ForwardNode(call to lookup_by_extension) |
| mime_type.rb:6:6:6:47 | ForwardNode(call to register) |
| mime_type.rb:7:6:7:64 | ForwardNode(call to register_alias) |
mimeTypeMatchRegExpInterpretations
| mime_type.rb:11:11:11:19 | "foo/bar" |
| mime_type.rb:12:7:12:15 | "foo/bar" |
| mime_type.rb:13:11:13:11 | s |
| mime_type.rb:14:7:14:7 | s |
requestInputAccesses
| app/controllers/comments_controller.rb:3:5:3:18 | call to params |
| app/controllers/comments_controller.rb:4:5:4:22 | call to parameters |
| app/controllers/comments_controller.rb:5:5:5:15 | call to GET |
| app/controllers/comments_controller.rb:6:5:6:16 | call to POST |
| app/controllers/comments_controller.rb:7:5:7:28 | call to query_parameters |
| app/controllers/comments_controller.rb:8:5:8:30 | call to request_parameters |
| app/controllers/comments_controller.rb:9:5:9:31 | call to filtered_parameters |
| app/controllers/comments_controller.rb:38:5:38:14 | call to params |
| app/controllers/foo/bars_controller.rb:10:27:10:33 | call to cookies |
| app/controllers/foo/bars_controller.rb:13:21:13:26 | call to params |
| app/controllers/foo/bars_controller.rb:14:10:14:15 | call to params |
| app/controllers/foo/bars_controller.rb:21:21:21:26 | call to params |
| app/controllers/foo/bars_controller.rb:22:10:22:15 | call to params |

View File

@@ -2,6 +2,7 @@ private import codeql.ruby.AST
private import codeql.ruby.frameworks.ActionDispatch
private import codeql.ruby.frameworks.ActionController
private import codeql.ruby.ApiGraphs
private import codeql.ruby.Concepts
private import codeql.ruby.frameworks.data.ModelsAsData
private import codeql.ruby.DataFlow
private import codeql.ruby.Regexp as RE
@@ -36,3 +37,5 @@ query predicate mimeTypeMatchRegExpInterpretations(
) {
any()
}
query predicate requestInputAccesses(Http::Server::RequestInputAccess a) { any() }

View File

@@ -33,6 +33,9 @@ class CommentsController < ApplicationController
response.last_modified = Date.yesterday
response.weak_etag = "value"
response.strong_etag = "value"
req = ActionDispatch::Request.new(request.env)
req.params
end
def show

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| mailer.rb:3:10:3:15 | call to params | mailer.rb:3:10:3:21 | ...[...] |
nodes

View File

@@ -7,12 +7,14 @@ import TestUtilities.InlineFlowTest
import PathGraph
import codeql.ruby.frameworks.Rails
class ParamsTaintFlowConf extends DefaultTaintFlowConf {
override predicate isSource(DataFlow::Node n) {
n.asExpr().getExpr() instanceof Rails::ParamsCall
}
module ParamsTaintFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n.asExpr().getExpr() instanceof Rails::ParamsCall }
predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ParamsTaintFlowConf conf
where conf.hasFlowPath(source, sink)
import FlowTest<DefaultFlowConfig, ParamsTaintFlowConfig>
from TaintFlow::PathNode source, TaintFlow::PathNode sink
where TaintFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -10,6 +10,7 @@ activeRecordInstances
| ActiveRecord.rb:9:5:9:68 | call to find |
| ActiveRecord.rb:13:5:13:40 | call to find_by |
| ActiveRecord.rb:13:5:13:46 | call to users |
| ActiveRecord.rb:35:5:35:51 | call to authenticate |
| ActiveRecord.rb:36:5:36:30 | call to find_by_name |
| ActiveRecord.rb:55:5:57:7 | if ... |
| ActiveRecord.rb:55:43:56:40 | then ... |
@@ -107,12 +108,14 @@ activeRecordSqlExecutionRanges
| ActiveRecord.rb:19:16:19:24 | condition |
| ActiveRecord.rb:28:30:28:44 | ...[...] |
| ActiveRecord.rb:29:20:29:42 | "id = '#{...}'" |
| ActiveRecord.rb:30:21:30:45 | call to [] |
| ActiveRecord.rb:30:22:30:44 | "id = '#{...}'" |
| ActiveRecord.rb:31:16:31:21 | <<-SQL |
| ActiveRecord.rb:34:20:34:47 | "user.id = '#{...}'" |
| ActiveRecord.rb:46:20:46:32 | ... + ... |
| ActiveRecord.rb:52:16:52:28 | "name #{...}" |
| ActiveRecord.rb:56:20:56:39 | "username = #{...}" |
| ActiveRecord.rb:68:21:68:44 | ...[...] |
| ActiveRecord.rb:106:27:106:76 | "this is an unsafe annotation:..." |
activeRecordModelClassMethodCalls
| ActiveRecord.rb:2:3:2:17 | call to has_many |
@@ -127,7 +130,6 @@ activeRecordModelClassMethodCalls
| ActiveRecord.rb:31:5:31:35 | call to where |
| ActiveRecord.rb:34:5:34:14 | call to where |
| ActiveRecord.rb:34:5:34:48 | call to not |
| ActiveRecord.rb:35:5:35:51 | call to authenticate |
| ActiveRecord.rb:36:5:36:30 | call to find_by_name |
| ActiveRecord.rb:37:5:37:36 | call to not_a_find_by_method |
| ActiveRecord.rb:46:5:46:33 | call to delete_by |
@@ -135,7 +137,6 @@ activeRecordModelClassMethodCalls
| ActiveRecord.rb:56:7:56:40 | call to find_by |
| ActiveRecord.rb:60:5:60:33 | call to find_by |
| ActiveRecord.rb:62:5:62:34 | call to find |
| ActiveRecord.rb:68:5:68:45 | call to delete_by |
| ActiveRecord.rb:72:5:72:24 | call to create |
| ActiveRecord.rb:76:5:76:66 | call to create |
| ActiveRecord.rb:80:5:80:68 | call to create |
@@ -152,6 +153,96 @@ activeRecordModelClassMethodCalls
| associations.rb:12:3:12:32 | call to has_and_belongs_to_many |
| associations.rb:16:3:16:18 | call to belongs_to |
| associations.rb:19:11:19:20 | call to new |
| associations.rb:21:9:21:21 | call to posts |
| associations.rb:21:9:21:28 | call to create |
| associations.rb:23:12:23:25 | call to comments |
| associations.rb:23:12:23:32 | call to create |
| associations.rb:25:11:25:22 | call to author |
| associations.rb:27:9:27:21 | call to posts |
| associations.rb:27:9:27:28 | call to create |
| associations.rb:29:1:29:13 | call to posts |
| associations.rb:29:1:29:22 | ... << ... |
| associations.rb:31:1:31:12 | call to author= |
| associations.rb:35:1:35:14 | call to comments |
| associations.rb:35:1:35:21 | call to create |
| associations.rb:35:1:35:28 | call to create |
| associations.rb:37:1:37:13 | call to posts |
| associations.rb:37:1:37:20 | call to reload |
| associations.rb:37:1:37:27 | call to create |
| associations.rb:39:1:39:15 | call to build_tag |
| associations.rb:40:1:40:15 | call to build_tag |
| associations.rb:42:1:42:13 | call to posts |
| associations.rb:42:1:42:25 | call to push |
| associations.rb:43:1:43:13 | call to posts |
| associations.rb:43:1:43:27 | call to concat |
| associations.rb:44:1:44:13 | call to posts |
| associations.rb:44:1:44:19 | call to build |
| associations.rb:45:1:45:13 | call to posts |
| associations.rb:45:1:45:20 | call to create |
| associations.rb:46:1:46:13 | call to posts |
| associations.rb:46:1:46:21 | call to create! |
| associations.rb:47:1:47:13 | call to posts |
| associations.rb:47:1:47:20 | call to delete |
| associations.rb:48:1:48:13 | call to posts |
| associations.rb:48:1:48:24 | call to delete_all |
| associations.rb:49:1:49:13 | call to posts |
| associations.rb:49:1:49:21 | call to destroy |
| associations.rb:50:1:50:13 | call to posts |
| associations.rb:50:1:50:25 | call to destroy_all |
| associations.rb:51:1:51:13 | call to posts |
| associations.rb:51:1:51:22 | call to distinct |
| associations.rb:51:1:51:36 | call to find |
| associations.rb:52:1:52:13 | call to posts |
| associations.rb:52:1:52:19 | call to reset |
| associations.rb:52:1:52:33 | call to find |
| associations.rb:53:1:53:13 | call to posts |
| associations.rb:53:1:53:20 | call to reload |
| associations.rb:53:1:53:34 | call to find |
activeRecordModelClassMethodCallsReplacement
| ActiveRecord.rb:1:1:3:3 | UserGroup | ActiveRecord.rb:2:3:2:17 | call to has_many |
| ActiveRecord.rb:1:1:3:3 | UserGroup | ActiveRecord.rb:13:5:13:40 | call to find_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:6:3:6:24 | call to belongs_to |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:9:5:9:68 | call to find |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:19:5:19:25 | call to destroy_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:28:5:28:45 | call to calculate |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:29:5:29:43 | call to delete_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:30:5:30:46 | call to destroy_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:31:5:31:35 | call to where |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:34:5:34:14 | call to where |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:35:5:35:51 | call to authenticate |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:36:5:36:30 | call to find_by_name |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:37:5:37:36 | call to not_a_find_by_method |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:46:5:46:33 | call to delete_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:52:5:52:29 | call to order |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:56:7:56:40 | call to find_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:60:5:60:33 | call to find_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:62:5:62:34 | call to find |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:68:5:68:45 | call to delete_by |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:72:5:72:24 | call to create |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:76:5:76:66 | call to create |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:80:5:80:68 | call to create |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:84:5:84:16 | call to create |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:88:5:88:27 | call to update |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:92:5:92:69 | call to update |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:96:5:96:71 | call to update |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:102:13:102:54 | call to annotate |
| ActiveRecord.rb:5:1:15:3 | User | ActiveRecord.rb:106:13:106:77 | call to annotate |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:19:5:19:25 | call to destroy_by |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:68:5:68:45 | call to delete_by |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:72:5:72:24 | call to create |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:76:5:76:66 | call to create |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:80:5:80:68 | call to create |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:84:5:84:16 | call to create |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:88:5:88:27 | call to update |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:92:5:92:69 | call to update |
| ActiveRecord.rb:17:1:21:3 | Admin | ActiveRecord.rb:96:5:96:71 | call to update |
| associations.rb:1:1:3:3 | Author | associations.rb:2:3:2:17 | call to has_many |
| associations.rb:1:1:3:3 | Author | associations.rb:19:11:19:20 | call to new |
| associations.rb:5:1:9:3 | Post | associations.rb:6:3:6:20 | call to belongs_to |
| associations.rb:5:1:9:3 | Post | associations.rb:7:3:7:20 | call to has_many |
| associations.rb:5:1:9:3 | Post | associations.rb:8:3:8:31 | call to has_and_belongs_to_many |
| associations.rb:11:1:13:3 | Tag | associations.rb:12:3:12:32 | call to has_and_belongs_to_many |
| associations.rb:15:1:17:3 | Comment | associations.rb:16:3:16:18 | call to belongs_to |
potentiallyUnsafeSqlExecutingMethodCall
| ActiveRecord.rb:9:5:9:68 | call to find |
| ActiveRecord.rb:19:5:19:25 | call to destroy_by |

View File

@@ -9,9 +9,19 @@ query predicate activeRecordInstances(ActiveRecordInstance i) { any() }
query predicate activeRecordSqlExecutionRanges(ActiveRecordSqlExecutionRange range) { any() }
query predicate activeRecordModelClassMethodCalls(ActiveRecordModelClassMethodCall call) { any() }
deprecated query predicate activeRecordModelClassMethodCalls(ActiveRecordModelClassMethodCall call) {
any()
}
query predicate potentiallyUnsafeSqlExecutingMethodCall(PotentiallyUnsafeSqlExecutingMethodCall call) {
query predicate activeRecordModelClassMethodCallsReplacement(
ActiveRecordModelClass cls, DataFlow::CallNode call
) {
call = cls.getClassNode().trackModule().getAMethodCall(_)
}
deprecated query predicate potentiallyUnsafeSqlExecutingMethodCall(
PotentiallyUnsafeSqlExecutingMethodCall call
) {
any()
}

View File

@@ -33,6 +33,13 @@ modelInstances
| active_resource.rb:26:9:26:14 | people |
| active_resource.rb:26:9:26:20 | call to first |
| active_resource.rb:27:1:27:5 | alice |
modelInstancesAsSource
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:5:9:5:33 | call to new |
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:8:9:8:22 | call to find |
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:16:1:16:23 | call to new |
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:18:1:18:22 | call to get |
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:24:10:24:26 | call to find |
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:26:9:26:20 | call to first |
modelInstanceMethodCalls
| active_resource.rb:6:1:6:10 | call to save |
| active_resource.rb:9:1:9:13 | call to address= |
@@ -50,3 +57,6 @@ collections
| active_resource.rb:24:1:24:26 | ... = ... |
| active_resource.rb:24:10:24:26 | call to find |
| active_resource.rb:26:9:26:14 | people |
collectionSources
| active_resource.rb:23:10:23:19 | call to all |
| active_resource.rb:24:10:24:26 | call to find |

View File

@@ -3,7 +3,8 @@ import codeql.ruby.DataFlow
import codeql.ruby.frameworks.ActiveResource
query predicate modelClasses(
ActiveResource::ModelClass c, DataFlow::Node siteAssignCall, boolean disablesCertificateValidation
ActiveResource::ModelClassNode c, DataFlow::Node siteAssignCall,
boolean disablesCertificateValidation
) {
c.getASiteAssignment() = siteAssignCall and
if c.disablesCertificateValidation(siteAssignCall)
@@ -13,8 +14,16 @@ query predicate modelClasses(
query predicate modelClassMethodCalls(ActiveResource::ModelClassMethodCall c) { any() }
query predicate modelInstances(ActiveResource::ModelInstance c) { any() }
deprecated query predicate modelInstances(ActiveResource::ModelInstance c) { any() }
query predicate modelInstancesAsSource(
ActiveResource::ModelClassNode cls, DataFlow::LocalSourceNode node
) {
node = cls.getAnInstanceReference().asSource()
}
query predicate modelInstanceMethodCalls(ActiveResource::ModelInstanceMethodCall c) { any() }
query predicate collections(ActiveResource::Collection c) { any() }
deprecated query predicate collections(ActiveResource::Collection c) { any() }
query predicate collectionSources(ActiveResource::CollectionSource c) { any() }

View File

@@ -1,4 +1,5 @@
failures
testFailures
| hash_extensions.rb:126:10:126:19 | call to sole | Unexpected result: hasValueFlow=b |
edges
| active_support.rb:10:5:10:5 | x | active_support.rb:11:10:11:10 | x |

View File

@@ -5,8 +5,9 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import codeql.ruby.Frameworks
import DefaultFlowTest
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
where conf.hasFlowPath(source, sink)
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,3 +1,4 @@
failures
testFailures
#select
| arel.rb:3:8:3:18 | call to sql | arel.rb:2:7:2:14 | call to source | arel.rb:3:8:3:18 | call to sql | $@ | arel.rb:2:7:2:14 | call to source | call to source |

View File

@@ -5,7 +5,8 @@
import codeql.ruby.frameworks.Arel
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import DefaultFlowTest
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultTaintFlowConf conf
where conf.hasFlowPath(source, sink)
from TaintFlow::PathNode source, TaintFlow::PathNode sink
where TaintFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,4 +1,5 @@
failures
testFailures
edges
| json.rb:1:17:1:26 | call to source | json.rb:1:6:1:27 | call to parse |
| json.rb:2:18:2:27 | call to source | json.rb:2:6:2:28 | call to parse! |

View File

@@ -4,4 +4,5 @@
import TestUtilities.InlineFlowTest
import codeql.ruby.Frameworks
import DefaultFlowTest
import PathGraph

View File

@@ -0,0 +1,5 @@
| Mysql2.rb:10:16:10:48 | call to query | Mysql2.rb:10:27:10:47 | "SELECT * FROM users" |
| Mysql2.rb:13:16:13:73 | call to query | Mysql2.rb:13:27:13:72 | "SELECT * FROM users WHERE use..." |
| Mysql2.rb:17:16:17:76 | call to query | Mysql2.rb:17:27:17:75 | "SELECT * FROM users WHERE use..." |
| Mysql2.rb:21:16:21:57 | call to execute | Mysql2.rb:20:31:20:82 | "SELECT * FROM users WHERE id ..." |
| Mysql2.rb:25:16:25:60 | call to execute | Mysql2.rb:24:31:24:93 | "SELECT * FROM users WHERE use..." |

View File

@@ -0,0 +1,5 @@
private import codeql.ruby.DataFlow
private import codeql.ruby.Concepts
private import codeql.ruby.frameworks.Mysql2
query predicate mysql2SqlExecution(SqlExecution e, DataFlow::Node sql) { sql = e.getSql() }

View File

@@ -0,0 +1,30 @@
class UsersController < ActionController::Base
def mysql2_handler(event:, context:)
name = params[:user_name]
conn = Mysql2::Client.new(
host: "127.0.0.1",
username: "root"
)
# GOOD: SQL statement is not constructed from user input
results1 = conn.query("SELECT * FROM users")
# BAD: SQL statement constructed from user input
results2 = conn.query("SELECT * FROM users WHERE username='#{name}'")
# GOOD: user input is escaped
escaped = Mysql2::Client.escape(name)
results3 = conn.query("SELECT * FROM users WHERE username='#{escaped}'")
# GOOD: user input is escaped
statement1 = conn.prepare("SELECT * FROM users WHERE id >= ? AND username = ?")
results4 = statement1.execute(1, name, :as => :array)
# BAD: SQL statement constructed from user input
statement2 = conn.prepare("SELECT * FROM users WHERE username='#{name}' AND password = ?")
results4 = statement2.execute("password", :as => :array)
# NOT EXECUTED
statement3 = conn.prepare("SELECT * FROM users WHERE username = ?")
end
end

View File

@@ -57,17 +57,17 @@ pathnameInstances
| Pathname.rb:39:12:39:19 | foo_path |
| Pathname.rb:41:1:41:3 | p08 |
| Pathname.rb:42:1:42:3 | p01 |
| file://:0:0:0:0 | parameter position 0 of + |
| file://:0:0:0:0 | parameter self of + |
| file://:0:0:0:0 | parameter self of Pathname;Method[cleanpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[expand_path] |
| file://:0:0:0:0 | parameter self of Pathname;Method[realpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | parameter self of Pathname;Method[sub_ext] |
| file://:0:0:0:0 | parameter self of Pathname;Method[to_path] |
| file://:0:0:0:0 | parameter self of join |
| file://:0:0:0:0 | parameter self of sub |
| file://:0:0:0:0 | parameter self of to_s |
| file://:0:0:0:0 | [summary param] position 0 in + |
| file://:0:0:0:0 | [summary param] self in + |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[cleanpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[expand_path] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[realpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[sub_ext] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[to_path] |
| file://:0:0:0:0 | [summary param] self in join |
| file://:0:0:0:0 | [summary param] self in sub |
| file://:0:0:0:0 | [summary param] self in to_s |
fileSystemAccesses
| Pathname.rb:26:12:26:24 | call to open | Pathname.rb:26:12:26:19 | foo_path |
| Pathname.rb:28:11:28:22 | call to opendir | Pathname.rb:28:11:28:14 | pwd1 |
@@ -134,17 +134,17 @@ fileNameSources
| Pathname.rb:39:12:39:19 | foo_path |
| Pathname.rb:41:1:41:3 | p08 |
| Pathname.rb:42:1:42:3 | p01 |
| file://:0:0:0:0 | parameter position 0 of + |
| file://:0:0:0:0 | parameter self of + |
| file://:0:0:0:0 | parameter self of Pathname;Method[cleanpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[expand_path] |
| file://:0:0:0:0 | parameter self of Pathname;Method[realpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | parameter self of Pathname;Method[sub_ext] |
| file://:0:0:0:0 | parameter self of Pathname;Method[to_path] |
| file://:0:0:0:0 | parameter self of join |
| file://:0:0:0:0 | parameter self of sub |
| file://:0:0:0:0 | parameter self of to_s |
| file://:0:0:0:0 | [summary param] position 0 in + |
| file://:0:0:0:0 | [summary param] self in + |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[cleanpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[expand_path] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[realpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[sub_ext] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[to_path] |
| file://:0:0:0:0 | [summary param] self in join |
| file://:0:0:0:0 | [summary param] self in sub |
| file://:0:0:0:0 | [summary param] self in to_s |
fileSystemReadAccesses
| Pathname.rb:32:12:32:24 | call to read | Pathname.rb:32:12:32:24 | call to read |
fileSystemWriteAccesses

View File

@@ -1,4 +1,26 @@
| rack.rb:1:1:5:3 | HelloWorld | rack.rb:2:12:2:14 | env |
| rack.rb:7:1:16:3 | Proxy | rack.rb:12:12:12:18 | the_env |
| rack.rb:18:1:31:3 | Logger | rack.rb:24:12:24:14 | env |
| rack.rb:45:1:61:3 | Baz | rack.rb:46:12:46:14 | env |
rackRequestHandlers
| rack.rb:2:3:9:5 | call | rack.rb:2:12:2:14 | env | rack.rb:8:5:8:38 | call to [] |
| rack.rb:17:3:21:5 | call | rack.rb:17:12:17:18 | the_env | rack.rb:20:5:20:27 | call to [] |
| rack.rb:30:3:36:5 | call | rack.rb:30:12:30:14 | env | rack.rb:35:5:35:26 | call to [] |
| rack.rb:40:3:44:5 | call | rack.rb:40:12:40:14 | env | rack.rb:43:5:43:45 | call to [] |
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:66:7:66:24 | call to [] |
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:73:5:73:23 | call to [] |
| rack.rb:79:3:81:5 | call | rack.rb:79:17:79:19 | env | rack.rb:93:5:93:78 | call to finish |
| rack.rb:98:3:107:5 | call | rack.rb:98:12:98:14 | env | rack.rb:110:5:110:28 | call to [] |
| rack.rb:98:3:107:5 | call | rack.rb:98:12:98:14 | env | rack.rb:114:5:114:30 | call to [] |
| rack.rb:119:3:123:5 | call | rack.rb:119:12:119:14 | env | rack.rb:122:5:122:42 | call to [] |
| rack_apps.rb:6:3:12:5 | call | rack_apps.rb:6:12:6:14 | env | rack_apps.rb:10:12:10:34 | call to [] |
| rack_apps.rb:16:3:18:5 | call | rack_apps.rb:16:17:16:19 | env | rack_apps.rb:17:5:17:28 | call to [] |
| rack_apps.rb:21:14:21:50 | -> { ... } | rack_apps.rb:21:17:21:19 | env | rack_apps.rb:21:24:21:48 | call to [] |
| rack_apps.rb:23:21:23:53 | { ... } | rack_apps.rb:23:24:23:26 | env | rack_apps.rb:23:29:23:51 | call to [] |
rackResponseContentTypes
| rack.rb:8:5:8:38 | call to [] | rack.rb:7:34:7:45 | "text/plain" |
| rack.rb:20:5:20:27 | call to [] | rack.rb:19:28:19:38 | "text/html" |
redirectResponses
| rack.rb:43:5:43:45 | call to [] | rack.rb:42:30:42:40 | "/foo.html" |
| rack.rb:93:5:93:78 | call to finish | rack.rb:93:60:93:70 | redirect_to |
requestInputAccesses
| rack.rb:100:18:100:28 | call to cookies |
| rack.rb:103:14:103:23 | call to params |
| rack.rb:104:18:104:32 | ...[...] |
| rack.rb:120:14:120:32 | ...[...] |

View File

@@ -1,4 +1,22 @@
private import codeql.ruby.AST
private import codeql.ruby.Concepts
private import codeql.ruby.frameworks.Rack
private import codeql.ruby.DataFlow
query predicate rackApps(Rack::AppCandidate c, DataFlow::ParameterNode env) { env = c.getEnv() }
query predicate rackRequestHandlers(
Rack::App::RequestHandler handler, DataFlow::ParameterNode env, Rack::Response::ResponseNode resp
) {
env = handler.getEnv() and resp = handler.getAResponse()
}
query predicate rackResponseContentTypes(
Rack::Response::ResponseNode resp, DataFlow::Node contentType
) {
contentType = resp.getMimetypeOrContentTypeArg()
}
query predicate redirectResponses(Rack::Response::RedirectResponse resp, DataFlow::Node location) {
location = resp.getRedirectLocation()
}
query predicate requestInputAccesses(Http::Server::RequestInputAccess ria) { any() }

View File

@@ -1,6 +1,11 @@
class HelloWorld
def call(env)
[200, {'Content-Type' => 'text/plain'}, ['Hello World']]
status = 200
if something_goes_wrong(env)
status = 500
end
headers = {'Content-Type' => 'text/plain'}
[status, headers, ['Hello World']]
end
end
@@ -11,6 +16,7 @@ class Proxy
def call(the_env)
status, headers, body = @app.call(the_env)
headers.content_type = "text/html"
[status, headers, body]
end
end
@@ -30,6 +36,14 @@ class Logger
end
end
class Redirector
def call(env)
status = 302
headers = {'location' => '/foo.html'}
[status, headers, ['this is a redirect']]
end
end
class Foo
def not_call(env)
[1, 2, 3]
@@ -49,13 +63,62 @@ class Baz
def run(env)
if env[:foo] == "foo"
[200, {}, "foo"]
[200, {}, ["foo"]]
else
error
end
end
def error
[400, {}, "nope"]
[400, {}, ["nope"]]
end
end
class Qux
attr_reader :env
def self.call(env)
new(env).call
end
def initialize(env)
@env = env
end
def call
do_redirect
end
def do_redirect
redirect_to = env['redirect_to']
Rack::Response.new(['redirecting'], 302, 'Location' => redirect_to).finish
end
end
class UsesRequest
def call(env)
req = Rack::Request.new(env)
if session = req.cookies['session']
reuse_session(session)
else
name = req.params['name']
password = req['password']
login(name, password)
end
end
def login(name, password)
[200, {}, "new session"]
end
def reuse_session(name, password)
[200, {}, "reuse session"]
end
end
class UsesEnvQueryParams
def call(env)
params = env['QUERY_STRING']
user = Rack::Utils.parse_query(params)["user"]
[200, {}, [lookup_user_profile(user)]]
end
end

View File

@@ -0,0 +1,28 @@
require 'rack'
require 'rack/handler/puma'
handler = Rack::Handler::Puma
class InstanceApp
def call(env)
status = 200
headers = {}
body = ["instance app"]
resp = [status, headers, body]
resp
end
end
class ClassApp
def self.call(env)
[200, {}, ["class app"]]
end
end
lambda_app = ->(env) { [200, {}, ["lambda app"]] }
proc_app = Proc.new { |env| [200, {}, ["proc app"]] }
handler.run InstanceApp.new
handler.run ClassApp
handler.run lambda_app
handler.run proc_app

View File

@@ -0,0 +1,23 @@
sequelSqlConstruction
| sequel.rb:62:29:62:49 | call to cast | sequel.rb:62:45:62:48 | name |
| sequel.rb:65:29:65:49 | call to function | sequel.rb:65:45:65:48 | name |
sequelSqlExecution
| sequel.rb:9:9:9:60 | ...[...] | sequel.rb:9:14:9:59 | "SELECT * FROM users WHERE use..." |
| sequel.rb:12:9:12:64 | call to run | sequel.rb:12:18:12:63 | "SELECT * FROM users WHERE use..." |
| sequel.rb:15:9:17:11 | call to fetch | sequel.rb:15:20:15:65 | "SELECT * FROM users WHERE use..." |
| sequel.rb:20:9:20:65 | ...[...] | sequel.rb:20:14:20:64 | "SELECT * FROM users WHERE use..." |
| sequel.rb:23:9:23:65 | call to execute | sequel.rb:23:22:23:65 | "SELECT * FROM users WHERE use..." |
| sequel.rb:26:9:26:71 | call to execute_ddl | sequel.rb:26:26:26:71 | "SELECT * FROM users WHERE use..." |
| sequel.rb:29:9:29:71 | call to execute_dui | sequel.rb:29:26:29:71 | "SELECT * FROM users WHERE use..." |
| sequel.rb:32:9:32:74 | call to execute_insert | sequel.rb:32:29:32:74 | "SELECT * FROM users WHERE use..." |
| sequel.rb:35:9:35:62 | ... << ... | sequel.rb:35:17:35:62 | "SELECT * FROM users WHERE use..." |
| sequel.rb:38:9:38:79 | call to fetch_rows | sequel.rb:38:25:38:70 | "SELECT * FROM users WHERE use..." |
| sequel.rb:41:9:41:81 | call to with_sql_all | sequel.rb:41:35:41:80 | "SELECT * FROM users WHERE use..." |
| sequel.rb:44:9:44:84 | call to with_sql_delete | sequel.rb:44:38:44:83 | "SELECT * FROM users WHERE use..." |
| sequel.rb:47:9:47:90 | call to with_sql_each | sequel.rb:47:36:47:81 | "SELECT * FROM users WHERE use..." |
| sequel.rb:50:9:50:83 | call to with_sql_first | sequel.rb:50:37:50:82 | "SELECT * FROM users WHERE use..." |
| sequel.rb:53:9:53:84 | call to with_sql_insert | sequel.rb:53:38:53:83 | "SELECT * FROM users WHERE use..." |
| sequel.rb:56:9:56:90 | call to with_sql_single_value | sequel.rb:56:44:56:89 | "SELECT * FROM users WHERE use..." |
| sequel.rb:59:9:59:84 | call to with_sql_update | sequel.rb:59:38:59:83 | "SELECT * FROM users WHERE use..." |
| sequel.rb:62:9:62:20 | ...[...] | sequel.rb:62:14:62:19 | :table |
| sequel.rb:65:9:65:20 | ...[...] | sequel.rb:65:14:65:19 | :table |

View File

@@ -0,0 +1,7 @@
private import codeql.ruby.DataFlow
private import codeql.ruby.Concepts
private import codeql.ruby.frameworks.Sequel
query predicate sequelSqlConstruction(SqlConstruction c, DataFlow::Node sql) { sql = c.getSql() }
query predicate sequelSqlExecution(SqlExecution e, DataFlow::Node sql) { sql = e.getSql() }

View File

@@ -0,0 +1,67 @@
require 'sequel'
class UsersController < ActionController::Base
def sequel_handler(event:, context:)
name = params[:name]
conn = Sequel.sqlite("sqlite://example.db")
# BAD: SQL statement constructed from user input
conn["SELECT * FROM users WHERE username='#{name}'"]
# BAD: SQL statement constructed from user input
conn.run("SELECT * FROM users WHERE username='#{name}'")
# BAD: SQL statement constructed from user input
conn.fetch("SELECT * FROM users WHERE username='#{name}'") do |row|
puts row[:name]
end
# GOOD: SQL statement is not constructed from user input
conn["SELECT * FROM users WHERE username='im_not_input'"]
# BAD: SQL statement constructed from user input
conn.execute "SELECT * FROM users WHERE username=#{name}"
# BAD: SQL statement constructed from user input
conn.execute_ddl "SELECT * FROM users WHERE username='#{name}'"
# BAD: SQL statement constructed from user input
conn.execute_dui "SELECT * FROM users WHERE username='#{name}'"
# BAD: SQL statement constructed from user input
conn.execute_insert "SELECT * FROM users WHERE username='#{name}'"
# BAD: SQL statement constructed from user input
conn << "SELECT * FROM users WHERE username='#{name}'"
# BAD: SQL statement constructed from user input
conn.fetch_rows("SELECT * FROM users WHERE username='#{name}'"){|row| }
# BAD: SQL statement constructed from user input
conn.dataset.with_sql_all("SELECT * FROM users WHERE username='#{name}'")
# BAD: SQL statement constructed from user input
conn.dataset.with_sql_delete("SELECT * FROM users WHERE username='#{name}'")
# BAD: SQL statement constructed from user input
conn.dataset.with_sql_each("SELECT * FROM users WHERE username='#{name}'"){|row| }
# BAD: SQL statement constructed from user input
conn.dataset.with_sql_first("SELECT * FROM users WHERE username='#{name}'")
# BAD: SQL statement constructed from user input
conn.dataset.with_sql_insert("SELECT * FROM users WHERE username='#{name}'")
# BAD: SQL statement constructed from user input
conn.dataset.with_sql_single_value("SELECT * FROM users WHERE username='#{name}'")
# BAD: SQL statement constructed from user input
conn.dataset.with_sql_update("SELECT * FROM users WHERE username='#{name}'")
# BAD: SQL statement constructed from user input
conn[:table].select(Sequel.cast(:a, name))
# BAD: SQL statement constructed from user input
conn[:table].select(Sequel.function(name))
end
end

View File

@@ -1,4 +1,5 @@
failures
testFailures
| views/index.erb:2:10:2:12 | call to foo | Unexpected result: hasTaintFlow= |
edges
| app.rb:75:5:75:8 | [post] self [@foo] | app.rb:76:32:76:35 | self [@foo] |

View File

@@ -8,12 +8,16 @@ import PathGraph
import codeql.ruby.frameworks.Sinatra
import codeql.ruby.Concepts
class SinatraConf extends DefaultTaintFlowConf {
override predicate isSource(DataFlow::Node source) {
module SinatraConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof Http::Server::RequestInputAccess::Range
}
predicate isSink(DataFlow::Node sink) { DefaultFlowConfig::isSink(sink) }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, SinatraConf conf
where conf.hasFlowPath(source, sink)
import FlowTest<DefaultFlowConfig, SinatraConfig>
from TaintFlow::PathNode source, TaintFlow::PathNode sink
where TaintFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -5,6 +5,6 @@ sqlite3SqlConstruction
| sqlite3.rb:29:7:29:40 | call to execute | sqlite3.rb:29:19:29:39 | "select * from table" |
sqlite3SqlExecution
| sqlite3.rb:5:1:5:17 | call to execute | sqlite3.rb:5:12:5:17 | <<-SQL |
| sqlite3.rb:14:1:14:12 | call to execute | sqlite3.rb:12:8:12:9 | db |
| sqlite3.rb:14:1:14:12 | call to execute | sqlite3.rb:12:19:12:41 | "select * from numbers" |
| sqlite3.rb:17:3:19:5 | call to execute | sqlite3.rb:17:15:17:35 | "select * from table" |
| sqlite3.rb:29:7:29:40 | call to execute | sqlite3.rb:29:19:29:39 | "select * from table" |

View File

@@ -94,64 +94,64 @@ calls.rb:
# 325| C1
#-----| super -> Object
# 331| C2
# 335| C2
#-----| super -> C1
# 337| C3
# 341| C3
#-----| super -> C2
# 377| SingletonOverride1
# 385| SingletonOverride1
#-----| super -> Object
# 412| SingletonOverride2
# 420| SingletonOverride2
#-----| super -> SingletonOverride1
# 433| ConditionalInstanceMethods
# 441| ConditionalInstanceMethods
#-----| super -> Object
# 496| ExtendSingletonMethod
# 504| ExtendSingletonMethod
# 506| ExtendSingletonMethod2
# 514| ExtendSingletonMethod2
# 512| ExtendSingletonMethod3
# 520| ExtendSingletonMethod3
# 525| ProtectedMethodInModule
# 533| ProtectedMethodInModule
# 531| ProtectedMethods
# 539| ProtectedMethods
#-----| super -> Object
#-----| include -> ProtectedMethodInModule
# 550| ProtectedMethodsSub
# 558| ProtectedMethodsSub
#-----| super -> ProtectedMethods
# 564| SingletonUpCall_Base
# 572| SingletonUpCall_Base
#-----| super -> Object
# 568| SingletonUpCall_Sub
# 576| SingletonUpCall_Sub
#-----| super -> SingletonUpCall_Base
# 576| SingletonUpCall_SubSub
# 584| SingletonUpCall_SubSub
#-----| super -> SingletonUpCall_Sub
# 583| SingletonA
# 591| SingletonA
#-----| super -> Object
# 596| SingletonB
# 604| SingletonB
#-----| super -> SingletonA
# 605| SingletonC
# 613| SingletonC
#-----| super -> SingletonA
# 618| Included
# 626| Included
# 626| IncludesIncluded
# 634| IncludesIncluded
#-----| super -> Object
#-----| include -> Included
# 633| CustomNew1
# 641| CustomNew1
#-----| super -> Object
# 641| CustomNew2
# 649| CustomNew2
#-----| super -> Object
hello.rb:

View File

@@ -117,134 +117,146 @@ getTarget
| calls.rb:320:5:320:16 | call to instance | calls.rb:311:5:314:7 | instance |
| calls.rb:323:1:323:17 | call to singleton | calls.rb:316:5:318:7 | singleton |
| calls.rb:327:9:327:26 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:333:9:333:26 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:339:9:339:26 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:346:9:346:18 | call to instance | calls.rb:338:5:340:7 | instance |
| calls.rb:348:9:348:18 | call to instance | calls.rb:332:5:334:7 | instance |
| calls.rb:348:9:348:18 | call to instance | calls.rb:338:5:340:7 | instance |
| calls.rb:350:9:350:18 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:350:9:350:18 | call to instance | calls.rb:332:5:334:7 | instance |
| calls.rb:350:9:350:18 | call to instance | calls.rb:338:5:340:7 | instance |
| calls.rb:355:20:355:29 | call to instance | calls.rb:338:5:340:7 | instance |
| calls.rb:356:26:356:36 | call to instance | calls.rb:332:5:334:7 | instance |
| calls.rb:356:26:356:36 | call to instance | calls.rb:338:5:340:7 | instance |
| calls.rb:357:26:357:36 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:357:26:357:36 | call to instance | calls.rb:332:5:334:7 | instance |
| calls.rb:357:26:357:36 | call to instance | calls.rb:338:5:340:7 | instance |
| calls.rb:361:6:361:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:362:1:362:11 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
| calls.rb:363:19:363:24 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
| calls.rb:364:19:364:24 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
| calls.rb:365:19:365:24 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:369:9:369:28 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:373:6:373:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:367:1:371:3 | add_singleton |
| calls.rb:375:1:375:11 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:375:1:375:11 | call to instance | calls.rb:368:5:370:7 | instance |
| calls.rb:380:13:380:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 |
| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:414:9:416:11 | singleton1 |
| calls.rb:388:13:388:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:388:13:388:30 | call to instance1 | calls.rb:402:5:404:7 | instance1 |
| calls.rb:388:13:388:30 | call to instance1 | calls.rb:423:5:425:7 | instance1 |
| calls.rb:393:9:393:44 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 |
| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:419:5:421:7 | singleton2 |
| calls.rb:400:5:400:14 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 |
| calls.rb:403:9:403:43 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:407:1:407:29 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 |
| calls.rb:408:1:408:29 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 |
| calls.rb:409:1:409:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 |
| calls.rb:410:1:410:34 | call to call_singleton2 | calls.rb:396:5:398:7 | call_singleton2 |
| calls.rb:415:13:415:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:420:9:420:44 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:424:9:424:43 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:428:1:428:29 | call to singleton1 | calls.rb:414:9:416:11 | singleton1 |
| calls.rb:429:1:429:29 | call to singleton2 | calls.rb:419:5:421:7 | singleton2 |
| calls.rb:430:1:430:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 |
| calls.rb:431:1:431:34 | call to call_singleton2 | calls.rb:396:5:398:7 | call_singleton2 |
| calls.rb:436:13:436:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:441:9:441:44 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:337:9:337:26 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:343:9:343:26 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:350:9:350:18 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:352:9:352:18 | call to instance | calls.rb:336:5:338:7 | instance |
| calls.rb:352:9:352:18 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:354:9:354:18 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:354:9:354:18 | call to instance | calls.rb:336:5:338:7 | instance |
| calls.rb:354:9:354:18 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:359:20:359:29 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:360:26:360:36 | call to instance | calls.rb:336:5:338:7 | instance |
| calls.rb:360:26:360:36 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:361:26:361:36 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:361:26:361:36 | call to instance | calls.rb:336:5:338:7 | instance |
| calls.rb:361:26:361:36 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:365:6:365:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:366:1:366:11 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:368:1:368:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:368:19:368:24 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:369:1:369:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:369:19:369:24 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:370:1:370:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:370:19:370:24 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:372:1:372:6 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:372:1:372:18 | call to return_self | calls.rb:330:5:332:7 | return_self |
| calls.rb:372:1:372:27 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:372:1:372:27 | call to instance | calls.rb:336:5:338:7 | instance |
| calls.rb:372:1:372:27 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:376:9:376:28 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:380:6:380:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:381:1:381:16 | call to add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:382:1:382:11 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:382:1:382:11 | call to instance | calls.rb:375:5:377:7 | instance |
| calls.rb:383:1:383:14 | call to return_self | calls.rb:330:5:332:7 | return_self |
| calls.rb:383:1:383:23 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:383:1:383:23 | call to instance | calls.rb:336:5:338:7 | instance |
| calls.rb:383:1:383:23 | call to instance | calls.rb:342:5:344:7 | instance |
| calls.rb:383:1:383:23 | call to instance | calls.rb:375:5:377:7 | instance |
| calls.rb:388:13:388:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:387:9:389:11 | singleton1 |
| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:422:9:424:11 | singleton1 |
| calls.rb:396:13:396:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:396:13:396:30 | call to instance1 | calls.rb:410:5:412:7 | instance1 |
| calls.rb:396:13:396:30 | call to instance1 | calls.rb:431:5:433:7 | instance1 |
| calls.rb:401:9:401:44 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 |
| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:427:5:429:7 | singleton2 |
| calls.rb:408:5:408:14 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 |
| calls.rb:411:9:411:43 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:415:1:415:29 | call to singleton1 | calls.rb:387:9:389:11 | singleton1 |
| calls.rb:416:1:416:29 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 |
| calls.rb:417:1:417:34 | call to call_singleton1 | calls.rb:391:9:393:11 | call_singleton1 |
| calls.rb:418:1:418:34 | call to call_singleton2 | calls.rb:404:5:406:7 | call_singleton2 |
| calls.rb:423:13:423:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:428:9:428:44 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:432:9:432:43 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:436:1:436:29 | call to singleton1 | calls.rb:422:9:424:11 | singleton1 |
| calls.rb:437:1:437:29 | call to singleton2 | calls.rb:427:5:429:7 | singleton2 |
| calls.rb:438:1:438:34 | call to call_singleton1 | calls.rb:391:9:393:11 | call_singleton1 |
| calls.rb:439:1:439:34 | call to call_singleton2 | calls.rb:404:5:406:7 | call_singleton2 |
| calls.rb:444:13:444:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:447:17:447:52 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:455:9:459:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:455:9:459:15 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:457:17:457:40 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:463:1:463:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:463:1:463:33 | call to m1 | calls.rb:435:9:437:11 | m1 |
| calls.rb:464:1:464:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:465:1:465:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:465:1:465:33 | call to m2 | calls.rb:440:5:452:7 | m2 |
| calls.rb:466:1:466:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:467:1:467:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:468:1:468:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:470:27:488:3 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:473:13:473:22 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:477:5:481:7 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:477:5:481:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:479:13:479:22 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:485:13:485:27 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:490:1:490:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:491:1:491:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:492:1:492:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:493:1:493:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:494:1:494:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:504:1:504:31 | call to singleton | calls.rb:497:5:499:7 | singleton |
| calls.rb:510:1:510:32 | call to singleton | calls.rb:497:5:499:7 | singleton |
| calls.rb:517:1:517:32 | call to singleton | calls.rb:497:5:499:7 | singleton |
| calls.rb:523:1:523:13 | call to singleton | calls.rb:497:5:499:7 | singleton |
| calls.rb:532:5:532:35 | call to include | calls.rb:108:5:110:7 | include |
| calls.rb:535:9:535:35 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:539:9:539:11 | call to foo | calls.rb:526:15:528:7 | foo |
| calls.rb:540:9:540:11 | call to bar | calls.rb:534:15:536:7 | bar |
| calls.rb:541:9:541:28 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:541:9:541:32 | call to foo | calls.rb:526:15:528:7 | foo |
| calls.rb:542:9:542:28 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:542:9:542:32 | call to bar | calls.rb:534:15:536:7 | bar |
| calls.rb:546:1:546:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:547:1:547:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:548:1:548:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:548:1:548:24 | call to baz | calls.rb:538:5:543:7 | baz |
| calls.rb:552:9:552:11 | call to foo | calls.rb:526:15:528:7 | foo |
| calls.rb:553:9:553:31 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:553:9:553:35 | call to foo | calls.rb:526:15:528:7 | foo |
| calls.rb:557:1:557:23 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:558:1:558:23 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:559:1:559:23 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:559:1:559:27 | call to baz | calls.rb:551:5:554:7 | baz |
| calls.rb:561:2:561:6 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:561:20:561:24 | call to baz | calls.rb:51:5:57:7 | baz |
| calls.rb:562:26:562:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize |
| calls.rb:569:5:569:13 | call to singleton | calls.rb:565:5:566:7 | singleton |
| calls.rb:572:9:572:17 | call to singleton | calls.rb:565:5:566:7 | singleton |
| calls.rb:573:9:573:18 | call to singleton2 | calls.rb:577:5:578:7 | singleton2 |
| calls.rb:580:5:580:14 | call to mid_method | calls.rb:571:5:574:7 | mid_method |
| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:584:5:585:7 | singleton1 |
| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:597:5:598:7 | singleton1 |
| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:606:5:607:7 | singleton1 |
| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:587:5:589:7 | call_singleton1 |
| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:600:5:602:7 | call_singleton1 |
| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:609:5:611:7 | call_singleton1 |
| calls.rb:601:9:601:18 | call to singleton1 | calls.rb:597:5:598:7 | singleton1 |
| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:606:5:607:7 | singleton1 |
| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
| calls.rb:620:9:620:16 | call to bar | calls.rb:622:5:623:7 | bar |
| calls.rb:620:9:620:16 | call to bar | calls.rb:628:5:630:7 | bar |
| calls.rb:627:5:627:20 | call to include | calls.rb:108:5:110:7 | include |
| calls.rb:629:9:629:13 | super call to bar | calls.rb:622:5:623:7 | bar |
| calls.rb:635:9:635:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:639:1:639:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:639:1:639:14 | call to new | calls.rb:634:5:636:7 | new |
| calls.rb:639:1:639:23 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:647:9:647:34 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:651:1:651:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:651:1:651:14 | call to new | calls.rb:642:5:644:7 | new |
| calls.rb:651:1:651:23 | call to instance | calls.rb:646:5:648:7 | instance |
| calls.rb:449:9:449:44 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:452:13:452:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:455:17:455:52 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:463:9:467:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:463:9:467:15 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:465:17:465:40 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:471:1:471:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:471:1:471:33 | call to m1 | calls.rb:443:9:445:11 | m1 |
| calls.rb:472:1:472:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:473:1:473:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:473:1:473:33 | call to m2 | calls.rb:448:5:460:7 | m2 |
| calls.rb:474:1:474:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:475:1:475:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:476:1:476:30 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:478:27:496:3 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:481:13:481:22 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:485:5:489:7 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:485:5:489:11 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:487:13:487:22 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:493:13:493:27 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:498:1:498:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:499:1:499:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:500:1:500:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:501:1:501:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:502:1:502:27 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:512:1:512:31 | call to singleton | calls.rb:505:5:507:7 | singleton |
| calls.rb:518:1:518:32 | call to singleton | calls.rb:505:5:507:7 | singleton |
| calls.rb:525:1:525:32 | call to singleton | calls.rb:505:5:507:7 | singleton |
| calls.rb:531:1:531:13 | call to singleton | calls.rb:505:5:507:7 | singleton |
| calls.rb:540:5:540:35 | call to include | calls.rb:108:5:110:7 | include |
| calls.rb:543:9:543:35 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:547:9:547:11 | call to foo | calls.rb:534:15:536:7 | foo |
| calls.rb:548:9:548:11 | call to bar | calls.rb:542:15:544:7 | bar |
| calls.rb:549:9:549:28 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:549:9:549:32 | call to foo | calls.rb:534:15:536:7 | foo |
| calls.rb:550:9:550:28 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:550:9:550:32 | call to bar | calls.rb:542:15:544:7 | bar |
| calls.rb:554:1:554:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:555:1:555:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:556:1:556:20 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:556:1:556:24 | call to baz | calls.rb:546:5:551:7 | baz |
| calls.rb:560:9:560:11 | call to foo | calls.rb:534:15:536:7 | foo |
| calls.rb:561:9:561:31 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:561:9:561:35 | call to foo | calls.rb:534:15:536:7 | foo |
| calls.rb:565:1:565:23 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:566:1:566:23 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:567:1:567:23 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:567:1:567:27 | call to baz | calls.rb:559:5:562:7 | baz |
| calls.rb:569:2:569:6 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:569:20:569:24 | call to baz | calls.rb:51:5:57:7 | baz |
| calls.rb:570:26:570:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize |
| calls.rb:577:5:577:13 | call to singleton | calls.rb:573:5:574:7 | singleton |
| calls.rb:580:9:580:17 | call to singleton | calls.rb:573:5:574:7 | singleton |
| calls.rb:581:9:581:18 | call to singleton2 | calls.rb:585:5:586:7 | singleton2 |
| calls.rb:588:5:588:14 | call to mid_method | calls.rb:579:5:582:7 | mid_method |
| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:592:5:593:7 | singleton1 |
| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:605:5:606:7 | singleton1 |
| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:614:5:615:7 | singleton1 |
| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:595:5:597:7 | call_singleton1 |
| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:608:5:610:7 | call_singleton1 |
| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:617:5:619:7 | call_singleton1 |
| calls.rb:609:9:609:18 | call to singleton1 | calls.rb:605:5:606:7 | singleton1 |
| calls.rb:618:9:618:18 | call to singleton1 | calls.rb:614:5:615:7 | singleton1 |
| calls.rb:622:1:622:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 |
| calls.rb:623:1:623:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 |
| calls.rb:624:1:624:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 |
| calls.rb:628:9:628:16 | call to bar | calls.rb:630:5:631:7 | bar |
| calls.rb:628:9:628:16 | call to bar | calls.rb:636:5:638:7 | bar |
| calls.rb:635:5:635:20 | call to include | calls.rb:108:5:110:7 | include |
| calls.rb:637:9:637:13 | super call to bar | calls.rb:630:5:631:7 | bar |
| calls.rb:643:9:643:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:647:1:647:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:647:1:647:14 | call to new | calls.rb:642:5:644:7 | new |
| calls.rb:647:1:647:23 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:655:9:655:34 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:659:1:659:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:659:1:659:14 | call to new | calls.rb:650:5:652:7 | new |
| calls.rb:659:1:659:23 | call to instance | calls.rb:654:5:656:7 | instance |
| calls.rb:667:2:667:25 | call to capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:667:20:667:25 | call to new | calls.rb:117:5:117:16 | new |
| hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include |
| hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello |
| hello.rb:20:16:20:20 | super call to message | hello.rb:13:5:15:7 | message |
@@ -330,46 +342,49 @@ unresolvedCall
| calls.rb:274:1:274:14 | call to singleton_g |
| calls.rb:276:1:276:14 | call to singleton_g |
| calls.rb:313:9:313:20 | call to instance |
| calls.rb:434:8:434:13 | call to rand |
| calls.rb:434:8:434:17 | ... > ... |
| calls.rb:451:9:451:10 | call to m3 |
| calls.rb:454:8:454:13 | call to rand |
| calls.rb:454:8:454:17 | ... > ... |
| calls.rb:455:9:459:18 | call to m5 |
| calls.rb:464:1:464:33 | call to m3 |
| calls.rb:466:1:466:33 | call to m3 |
| calls.rb:467:1:467:33 | call to m4 |
| calls.rb:468:1:468:33 | call to m5 |
| calls.rb:471:5:471:11 | call to [] |
| calls.rb:471:5:475:7 | call to each |
| calls.rb:477:5:481:15 | call to bar |
| calls.rb:483:5:483:11 | call to [] |
| calls.rb:483:5:487:7 | call to each |
| calls.rb:484:9:486:11 | call to define_method |
| calls.rb:490:1:490:31 | call to foo |
| calls.rb:491:1:491:31 | call to bar |
| calls.rb:492:1:492:33 | call to baz_0 |
| calls.rb:493:1:493:33 | call to baz_1 |
| calls.rb:494:1:494:33 | call to baz_2 |
| calls.rb:498:9:498:46 | call to puts |
| calls.rb:501:5:501:15 | call to extend |
| calls.rb:507:5:507:32 | call to extend |
| calls.rb:515:1:515:51 | call to extend |
| calls.rb:520:1:520:13 | call to singleton |
| calls.rb:521:1:521:32 | call to extend |
| calls.rb:526:5:528:7 | call to protected |
| calls.rb:527:9:527:42 | call to puts |
| calls.rb:442:8:442:13 | call to rand |
| calls.rb:442:8:442:17 | ... > ... |
| calls.rb:459:9:459:10 | call to m3 |
| calls.rb:462:8:462:13 | call to rand |
| calls.rb:462:8:462:17 | ... > ... |
| calls.rb:463:9:467:18 | call to m5 |
| calls.rb:472:1:472:33 | call to m3 |
| calls.rb:474:1:474:33 | call to m3 |
| calls.rb:475:1:475:33 | call to m4 |
| calls.rb:476:1:476:33 | call to m5 |
| calls.rb:479:5:479:11 | call to [] |
| calls.rb:479:5:483:7 | call to each |
| calls.rb:485:5:489:15 | call to bar |
| calls.rb:491:5:491:11 | call to [] |
| calls.rb:491:5:495:7 | call to each |
| calls.rb:492:9:494:11 | call to define_method |
| calls.rb:498:1:498:31 | call to foo |
| calls.rb:499:1:499:31 | call to bar |
| calls.rb:500:1:500:33 | call to baz_0 |
| calls.rb:501:1:501:33 | call to baz_1 |
| calls.rb:502:1:502:33 | call to baz_2 |
| calls.rb:506:9:506:46 | call to puts |
| calls.rb:509:5:509:15 | call to extend |
| calls.rb:515:5:515:32 | call to extend |
| calls.rb:523:1:523:51 | call to extend |
| calls.rb:528:1:528:13 | call to singleton |
| calls.rb:529:1:529:32 | call to extend |
| calls.rb:534:5:536:7 | call to protected |
| calls.rb:546:1:546:24 | call to foo |
| calls.rb:547:1:547:24 | call to bar |
| calls.rb:557:1:557:27 | call to foo |
| calls.rb:558:1:558:27 | call to bar |
| calls.rb:561:1:561:7 | call to [] |
| calls.rb:561:1:561:26 | call to each |
| calls.rb:562:1:562:13 | call to [] |
| calls.rb:562:1:562:39 | call to each |
| calls.rb:570:5:570:14 | call to singleton2 |
| calls.rb:643:9:643:21 | call to allocate |
| calls.rb:535:9:535:42 | call to puts |
| calls.rb:542:5:544:7 | call to protected |
| calls.rb:554:1:554:24 | call to foo |
| calls.rb:555:1:555:24 | call to bar |
| calls.rb:565:1:565:27 | call to foo |
| calls.rb:566:1:566:27 | call to bar |
| calls.rb:569:1:569:7 | call to [] |
| calls.rb:569:1:569:26 | call to each |
| calls.rb:570:1:570:13 | call to [] |
| calls.rb:570:1:570:39 | call to each |
| calls.rb:578:5:578:14 | call to singleton2 |
| calls.rb:651:9:651:21 | call to allocate |
| calls.rb:662:5:662:11 | call to [] |
| calls.rb:662:5:664:7 | call to each |
| calls.rb:667:1:667:35 | call to instance |
| hello.rb:20:16:20:26 | ... + ... |
| hello.rb:20:16:20:34 | ... + ... |
| hello.rb:20:16:20:40 | ... + ... |
@@ -397,10 +412,11 @@ privateMethod
| calls.rb:158:1:160:3 | indirect |
| calls.rb:185:1:186:3 | private_on_main |
| calls.rb:278:1:286:3 | create |
| calls.rb:343:1:359:3 | pattern_dispatch |
| calls.rb:367:1:371:3 | add_singleton |
| calls.rb:472:9:474:11 | foo |
| calls.rb:478:9:480:11 | bar |
| calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:374:1:378:3 | add_singleton |
| calls.rb:480:9:482:11 | foo |
| calls.rb:486:9:488:11 | bar |
| calls.rb:661:1:665:3 | capture_parameter |
| private.rb:2:11:3:5 | private1 |
| private.rb:8:3:9:5 | private2 |
| private.rb:14:3:15:5 | private3 |
@@ -459,42 +475,43 @@ publicMethod
| calls.rb:311:5:314:7 | instance |
| calls.rb:316:5:318:7 | singleton |
| calls.rb:326:5:328:7 | instance |
| calls.rb:332:5:334:7 | instance |
| calls.rb:338:5:340:7 | instance |
| calls.rb:368:5:370:7 | instance |
| calls.rb:379:9:381:11 | singleton1 |
| calls.rb:383:9:385:11 | call_singleton1 |
| calls.rb:387:9:389:11 | factory |
| calls.rb:392:5:394:7 | singleton2 |
| calls.rb:396:5:398:7 | call_singleton2 |
| calls.rb:402:5:404:7 | instance1 |
| calls.rb:414:9:416:11 | singleton1 |
| calls.rb:419:5:421:7 | singleton2 |
| calls.rb:423:5:425:7 | instance1 |
| calls.rb:435:9:437:11 | m1 |
| calls.rb:440:5:452:7 | m2 |
| calls.rb:443:9:449:11 | m3 |
| calls.rb:446:13:448:15 | m4 |
| calls.rb:456:13:458:15 | m5 |
| calls.rb:497:5:499:7 | singleton |
| calls.rb:538:5:543:7 | baz |
| calls.rb:551:5:554:7 | baz |
| calls.rb:565:5:566:7 | singleton |
| calls.rb:571:5:574:7 | mid_method |
| calls.rb:577:5:578:7 | singleton2 |
| calls.rb:584:5:585:7 | singleton1 |
| calls.rb:587:5:589:7 | call_singleton1 |
| calls.rb:591:5:593:7 | call_call_singleton1 |
| calls.rb:597:5:598:7 | singleton1 |
| calls.rb:600:5:602:7 | call_singleton1 |
| calls.rb:606:5:607:7 | singleton1 |
| calls.rb:609:5:611:7 | call_singleton1 |
| calls.rb:619:5:621:7 | foo |
| calls.rb:622:5:623:7 | bar |
| calls.rb:628:5:630:7 | bar |
| calls.rb:634:5:636:7 | new |
| calls.rb:330:5:332:7 | return_self |
| calls.rb:336:5:338:7 | instance |
| calls.rb:342:5:344:7 | instance |
| calls.rb:375:5:377:7 | instance |
| calls.rb:387:9:389:11 | singleton1 |
| calls.rb:391:9:393:11 | call_singleton1 |
| calls.rb:395:9:397:11 | factory |
| calls.rb:400:5:402:7 | singleton2 |
| calls.rb:404:5:406:7 | call_singleton2 |
| calls.rb:410:5:412:7 | instance1 |
| calls.rb:422:9:424:11 | singleton1 |
| calls.rb:427:5:429:7 | singleton2 |
| calls.rb:431:5:433:7 | instance1 |
| calls.rb:443:9:445:11 | m1 |
| calls.rb:448:5:460:7 | m2 |
| calls.rb:451:9:457:11 | m3 |
| calls.rb:454:13:456:15 | m4 |
| calls.rb:464:13:466:15 | m5 |
| calls.rb:505:5:507:7 | singleton |
| calls.rb:546:5:551:7 | baz |
| calls.rb:559:5:562:7 | baz |
| calls.rb:573:5:574:7 | singleton |
| calls.rb:579:5:582:7 | mid_method |
| calls.rb:585:5:586:7 | singleton2 |
| calls.rb:592:5:593:7 | singleton1 |
| calls.rb:595:5:597:7 | call_singleton1 |
| calls.rb:599:5:601:7 | call_call_singleton1 |
| calls.rb:605:5:606:7 | singleton1 |
| calls.rb:608:5:610:7 | call_singleton1 |
| calls.rb:614:5:615:7 | singleton1 |
| calls.rb:617:5:619:7 | call_singleton1 |
| calls.rb:627:5:629:7 | foo |
| calls.rb:630:5:631:7 | bar |
| calls.rb:636:5:638:7 | bar |
| calls.rb:642:5:644:7 | new |
| calls.rb:646:5:648:7 | instance |
| calls.rb:650:5:652:7 | new |
| calls.rb:654:5:656:7 | instance |
| hello.rb:2:5:4:7 | hello |
| hello.rb:5:5:7:7 | world |
| hello.rb:13:5:15:7 | message |
@@ -522,7 +539,7 @@ publicMethod
| toplevel_self_singleton.rb:26:9:27:11 | call_me |
| toplevel_self_singleton.rb:29:9:32:11 | call_you |
protectedMethod
| calls.rb:526:15:528:7 | foo |
| calls.rb:534:15:536:7 | bar |
| calls.rb:534:15:536:7 | foo |
| calls.rb:542:15:544:7 | bar |
| private.rb:32:3:33:5 | protected1 |
| private.rb:35:3:36:5 | protected2 |

View File

@@ -326,6 +326,10 @@ class C1
def instance
puts "C1#instance"
end
def return_self
self
end
end
class C2 < C1
@@ -360,10 +364,13 @@ end
c1 = C1.new
c1.instance
pattern_dispatch (C1.new)
pattern_dispatch (C2.new)
pattern_dispatch (C3.new)
C3.new.return_self.instance
def add_singleton x
def x.instance
puts "instance_on x"
@@ -373,6 +380,7 @@ end
c3 = C1.new
add_singleton c3
c3.instance
c3.return_self.instance
class SingletonOverride1
class << self
@@ -649,3 +657,11 @@ class CustomNew2
end
CustomNew2.new.instance
def capture_parameter x
[0,1,2].each do
x
end
end
(capture_parameter C1.new).instance # NoMethodError

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -90,62 +90,62 @@ calls.rb:
# 325| C1
#-----| -> Object
# 331| C2
# 335| C2
#-----| -> C1
# 337| C3
# 341| C3
#-----| -> C2
# 377| SingletonOverride1
# 385| SingletonOverride1
#-----| -> Object
# 412| SingletonOverride2
# 420| SingletonOverride2
#-----| -> SingletonOverride1
# 433| ConditionalInstanceMethods
# 441| ConditionalInstanceMethods
#-----| -> Object
# 496| ExtendSingletonMethod
# 504| ExtendSingletonMethod
# 506| ExtendSingletonMethod2
# 514| ExtendSingletonMethod2
# 512| ExtendSingletonMethod3
# 520| ExtendSingletonMethod3
# 525| ProtectedMethodInModule
# 533| ProtectedMethodInModule
# 531| ProtectedMethods
# 539| ProtectedMethods
#-----| -> Object
# 550| ProtectedMethodsSub
# 558| ProtectedMethodsSub
#-----| -> ProtectedMethods
# 564| SingletonUpCall_Base
# 572| SingletonUpCall_Base
#-----| -> Object
# 568| SingletonUpCall_Sub
# 576| SingletonUpCall_Sub
#-----| -> SingletonUpCall_Base
# 576| SingletonUpCall_SubSub
# 584| SingletonUpCall_SubSub
#-----| -> SingletonUpCall_Sub
# 583| SingletonA
# 591| SingletonA
#-----| -> Object
# 596| SingletonB
# 604| SingletonB
#-----| -> SingletonA
# 605| SingletonC
# 613| SingletonC
#-----| -> SingletonA
# 618| Included
# 626| Included
# 626| IncludesIncluded
# 634| IncludesIncluded
#-----| -> Object
# 633| CustomNew1
# 641| CustomNew1
#-----| -> Object
# 641| CustomNew2
# 649| CustomNew2
#-----| -> Object
hello.rb:

View File

@@ -3,11 +3,14 @@ edges
| LdapInjection.rb:5:10:5:15 | call to params | LdapInjection.rb:5:10:5:20 | ...[...] |
| LdapInjection.rb:5:10:5:20 | ...[...] | LdapInjection.rb:5:5:5:6 | dc |
| LdapInjection.rb:9:5:9:8 | name | LdapInjection.rb:29:62:29:73 | "cn=#{...}" |
| LdapInjection.rb:9:5:9:8 | name | LdapInjection.rb:33:87:33:92 | call to [] |
| LdapInjection.rb:9:5:9:8 | name | LdapInjection.rb:37:5:37:10 | filter |
| LdapInjection.rb:9:5:9:8 | name | LdapInjection.rb:33:88:33:91 | name |
| LdapInjection.rb:9:12:9:17 | call to params | LdapInjection.rb:9:12:9:29 | ...[...] |
| LdapInjection.rb:9:12:9:29 | ...[...] | LdapInjection.rb:9:5:9:8 | name |
| LdapInjection.rb:33:88:33:91 | name | LdapInjection.rb:33:87:33:92 | call to [] |
| LdapInjection.rb:33:88:33:91 | name | LdapInjection.rb:37:41:37:44 | name |
| LdapInjection.rb:37:5:37:10 | filter | LdapInjection.rb:38:62:38:67 | filter |
| LdapInjection.rb:37:14:37:45 | call to eq | LdapInjection.rb:37:5:37:10 | filter |
| LdapInjection.rb:37:41:37:44 | name | LdapInjection.rb:37:14:37:45 | call to eq |
nodes
| LdapInjection.rb:5:5:5:6 | dc | semmle.label | dc |
| LdapInjection.rb:5:10:5:15 | call to params | semmle.label | call to params |
@@ -18,7 +21,10 @@ nodes
| LdapInjection.rb:25:23:25:49 | "ou=people,dc=#{...},dc=com" | semmle.label | "ou=people,dc=#{...},dc=com" |
| LdapInjection.rb:29:62:29:73 | "cn=#{...}" | semmle.label | "cn=#{...}" |
| LdapInjection.rb:33:87:33:92 | call to [] | semmle.label | call to [] |
| LdapInjection.rb:33:88:33:91 | name | semmle.label | name |
| LdapInjection.rb:37:5:37:10 | filter | semmle.label | filter |
| LdapInjection.rb:37:14:37:45 | call to eq | semmle.label | call to eq |
| LdapInjection.rb:37:41:37:44 | name | semmle.label | name |
| LdapInjection.rb:38:62:38:67 | filter | semmle.label | filter |
subpaths
#select

View File

@@ -0,0 +1,59 @@
require 'libxml'
class FooController < ActionController::Base
def libxml_handler(event:, context:)
name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = LibXML::XML::Document.string(xml)
# GOOD: XPath query is not constructed from user input
results1 = doc.find_first('//foo')
# BAD: XPath query is constructed from user input
results2 = doc.find_first("//#{name}")
# GOOD: XPath query is not constructed from user input
results3 = doc.find('//foo')
# BAD: XPath query is constructed from user input
results4 = doc.find("//#{name}")
end
end
class BarController < ActionController::Base
def libxml_safe_handler(event:, context:)
safe_name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = REXML::Document.new(xml)
# GOOD: barrier guard prevents taint flow
safe_name = if ["foo", "foo2"].include? safe_name
safe_name
else
safe_name = "foo"
end
# GOOD: XPath query is not constructed from unsanitized user input
results5 = doc.find_first("//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results6 = doc.find("//#{safe_name}")
end
end

View File

@@ -0,0 +1,88 @@
require 'nokogiri'
class FooController < ActionController::Base
def nokogiri_handler(event:, context:)
name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = Nokogiri::XML.parse(xml)
# GOOD: XPath query is not constructed from user input
results1 = doc.at('//foo')
# BAD: XPath query is constructed from user input
results2 = doc.at("//#{name}")
# GOOD: XPath query is not constructed from user input
results3 = doc.xpath('//foo')
# BAD: XPath query is constructed from user input
results4 = doc.xpath("//#{name}")
# GOOD: XPath query is not constructed from user input
results5 = doc.at_xpath('//foo')
# BAD: XPath query is constructed from user input
results6 = doc.at_xpath("//#{name}")
# GOOD: XPath query is not constructed from user input
doc.xpath('//foo').each do |element|
puts element.text
end
# BAD: XPath query constructed from user input
doc.xpath("//#{name}").each do |element|
puts element.text
end
# GOOD: XPath query is not constructed from user input
doc.search('//foo').each do |element|
puts element.text
end
# BAD: XPath query constructed from user input
doc.search("//#{name}").each do |element|
puts element.text
end
end
end
class BarController < ActionController::Base
def nokogiri_safe_handler(event:, context:)
safe_name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = Nokogiri::XML.parse(xml)
# GOOD: barrier guard prevents taint flow
safe_name = if ["foo", "foo2"].include? safe_name
safe_name
else
safe_name = "foo"
end
# GOOD: XPath query is not constructed from unsanitized user input
results7 = doc.at("//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results8 = doc.xpath("//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results9 = doc.at_xpath("//#{safe_name}")
end
end

View File

@@ -0,0 +1,69 @@
require 'rexml'
class FooController < ActionController::Base
def rexml_handler(event:, context:)
name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = REXML::Document.new(xml)
# GOOD: XPath query is not constructed from user input
results1 = REXML::XPath.first(doc, "//foo")
# BAD: XPath query is constructed from user input
results2 = REXML::XPath.first(doc, "//#{name}")
# GOOD: XPath query is not constructed from user input
results3 = REXML::XPath.match(doc, "//foo", nil)
# BAD: XPath query is constructed from user input
results4 = REXML::XPath.match(doc, "//#{name}", nil)
# GOOD: XPath query is not constructed from user input
REXML::XPath.each(doc, "//foo") do |element|
puts element.text
end
# BAD: XPath query constructed from user input
REXML::XPath.each(doc, "//#{name}") do |element|
puts element.text
end
end
end
class BarController < ActionController::Base
def rexml_safe_handler(event:, context:)
safe_name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = REXML::Document.new(xml)
# GOOD: barrier guard prevents taint flow
safe_name = if ["foo", "foo2"].include? safe_name
safe_name
else
safe_name = "foo"
end
# GOOD: XPath query is not constructed from unsanitized user input
results5 = REXML::XPath.first(doc, "//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results6 = REXML::XPath.match(doc, "//#{safe_name}", nil)
end
end

View File

@@ -0,0 +1,49 @@
edges
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:21:31:21:41 | "//#{...}" |
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:27:25:27:35 | "//#{...}" |
| LibxmlInjection.rb:5:12:5:17 | call to params | LibxmlInjection.rb:5:12:5:29 | ...[...] |
| LibxmlInjection.rb:5:12:5:29 | ...[...] | LibxmlInjection.rb:5:5:5:8 | name |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:21:23:21:33 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:27:26:27:36 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:33:29:33:39 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:41:15:41:25 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:51:16:51:26 | "//#{...}" |
| NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:5:12:5:29 | ...[...] |
| NokogiriInjection.rb:5:12:5:29 | ...[...] | NokogiriInjection.rb:5:5:5:8 | name |
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:21:40:21:50 | "//#{...}" |
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:27:40:27:50 | "//#{...}" |
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:35:28:35:38 | "//#{...}" |
| RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:5:12:5:29 | ...[...] |
| RexmlInjection.rb:5:12:5:29 | ...[...] | RexmlInjection.rb:5:5:5:8 | name |
nodes
| LibxmlInjection.rb:5:5:5:8 | name | semmle.label | name |
| LibxmlInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
| LibxmlInjection.rb:5:12:5:29 | ...[...] | semmle.label | ...[...] |
| LibxmlInjection.rb:21:31:21:41 | "//#{...}" | semmle.label | "//#{...}" |
| LibxmlInjection.rb:27:25:27:35 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | semmle.label | name |
| NokogiriInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
| NokogiriInjection.rb:5:12:5:29 | ...[...] | semmle.label | ...[...] |
| NokogiriInjection.rb:21:23:21:33 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:27:26:27:36 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:33:29:33:39 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:41:15:41:25 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:51:16:51:26 | "//#{...}" | semmle.label | "//#{...}" |
| RexmlInjection.rb:5:5:5:8 | name | semmle.label | name |
| RexmlInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
| RexmlInjection.rb:5:12:5:29 | ...[...] | semmle.label | ...[...] |
| RexmlInjection.rb:21:40:21:50 | "//#{...}" | semmle.label | "//#{...}" |
| RexmlInjection.rb:27:40:27:50 | "//#{...}" | semmle.label | "//#{...}" |
| RexmlInjection.rb:35:28:35:38 | "//#{...}" | semmle.label | "//#{...}" |
subpaths
#select
| LibxmlInjection.rb:21:31:21:41 | "//#{...}" | LibxmlInjection.rb:5:12:5:17 | call to params | LibxmlInjection.rb:21:31:21:41 | "//#{...}" | XPath expression depends on a $@. | LibxmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| LibxmlInjection.rb:27:25:27:35 | "//#{...}" | LibxmlInjection.rb:5:12:5:17 | call to params | LibxmlInjection.rb:27:25:27:35 | "//#{...}" | XPath expression depends on a $@. | LibxmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:21:23:21:33 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:21:23:21:33 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:27:26:27:36 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:27:26:27:36 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:33:29:33:39 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:33:29:33:39 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:41:15:41:25 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:41:15:41:25 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:51:16:51:26 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:51:16:51:26 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| RexmlInjection.rb:21:40:21:50 | "//#{...}" | RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:21:40:21:50 | "//#{...}" | XPath expression depends on a $@. | RexmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| RexmlInjection.rb:27:40:27:50 | "//#{...}" | RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:27:40:27:50 | "//#{...}" | XPath expression depends on a $@. | RexmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| RexmlInjection.rb:35:28:35:38 | "//#{...}" | RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:35:28:35:38 | "//#{...}" | XPath expression depends on a $@. | RexmlInjection.rb:5:12:5:17 | call to params | user-provided value |

View File

@@ -0,0 +1 @@
experimental/xpath-injection/XpathInjection.ql

View File

@@ -0,0 +1,75 @@
edges
| unicode_normalization.rb:7:5:7:17 | unicode_input | unicode_normalization.rb:8:23:8:35 | unicode_input |
| unicode_normalization.rb:7:5:7:17 | unicode_input | unicode_normalization.rb:9:22:9:34 | unicode_input |
| unicode_normalization.rb:7:21:7:26 | call to params | unicode_normalization.rb:7:21:7:42 | ...[...] |
| unicode_normalization.rb:7:21:7:42 | ...[...] | unicode_normalization.rb:7:5:7:17 | unicode_input |
| unicode_normalization.rb:15:5:15:17 | unicode_input | unicode_normalization.rb:16:27:16:39 | unicode_input |
| unicode_normalization.rb:15:5:15:17 | unicode_input | unicode_normalization.rb:16:27:16:39 | unicode_input |
| unicode_normalization.rb:15:21:15:26 | call to params | unicode_normalization.rb:15:21:15:42 | ...[...] |
| unicode_normalization.rb:15:21:15:26 | call to params | unicode_normalization.rb:15:21:15:42 | ...[...] |
| unicode_normalization.rb:15:21:15:42 | ...[...] | unicode_normalization.rb:15:5:15:17 | unicode_input |
| unicode_normalization.rb:15:21:15:42 | ...[...] | unicode_normalization.rb:15:5:15:17 | unicode_input |
| unicode_normalization.rb:16:5:16:23 | unicode_input_manip | unicode_normalization.rb:17:23:17:41 | unicode_input_manip |
| unicode_normalization.rb:16:5:16:23 | unicode_input_manip | unicode_normalization.rb:18:22:18:40 | unicode_input_manip |
| unicode_normalization.rb:16:27:16:39 | unicode_input | unicode_normalization.rb:16:27:16:59 | call to sub |
| unicode_normalization.rb:16:27:16:39 | unicode_input | unicode_normalization.rb:16:27:16:59 | call to sub |
| unicode_normalization.rb:16:27:16:59 | call to sub | unicode_normalization.rb:16:5:16:23 | unicode_input_manip |
| unicode_normalization.rb:24:5:24:17 | unicode_input | unicode_normalization.rb:25:37:25:49 | unicode_input |
| unicode_normalization.rb:24:21:24:26 | call to params | unicode_normalization.rb:24:21:24:42 | ...[...] |
| unicode_normalization.rb:24:21:24:42 | ...[...] | unicode_normalization.rb:24:5:24:17 | unicode_input |
| unicode_normalization.rb:25:5:25:21 | unicode_html_safe | unicode_normalization.rb:26:23:26:39 | unicode_html_safe |
| unicode_normalization.rb:25:5:25:21 | unicode_html_safe | unicode_normalization.rb:27:22:27:38 | unicode_html_safe |
| unicode_normalization.rb:25:25:25:50 | call to html_escape | unicode_normalization.rb:25:5:25:21 | unicode_html_safe |
| unicode_normalization.rb:25:37:25:49 | unicode_input | unicode_normalization.rb:25:25:25:50 | call to html_escape |
| unicode_normalization.rb:33:5:33:17 | unicode_input | unicode_normalization.rb:34:40:34:52 | unicode_input |
| unicode_normalization.rb:33:21:33:26 | call to params | unicode_normalization.rb:33:21:33:42 | ...[...] |
| unicode_normalization.rb:33:21:33:42 | ...[...] | unicode_normalization.rb:33:5:33:17 | unicode_input |
| unicode_normalization.rb:34:5:34:21 | unicode_html_safe | unicode_normalization.rb:35:23:35:39 | unicode_html_safe |
| unicode_normalization.rb:34:5:34:21 | unicode_html_safe | unicode_normalization.rb:36:22:36:38 | unicode_html_safe |
| unicode_normalization.rb:34:25:34:53 | call to escapeHTML | unicode_normalization.rb:34:25:34:63 | call to html_safe |
| unicode_normalization.rb:34:25:34:63 | call to html_safe | unicode_normalization.rb:34:5:34:21 | unicode_html_safe |
| unicode_normalization.rb:34:40:34:52 | unicode_input | unicode_normalization.rb:34:25:34:53 | call to escapeHTML |
nodes
| unicode_normalization.rb:7:5:7:17 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:7:21:7:26 | call to params | semmle.label | call to params |
| unicode_normalization.rb:7:21:7:42 | ...[...] | semmle.label | ...[...] |
| unicode_normalization.rb:8:23:8:35 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:9:22:9:34 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:15:5:15:17 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:15:5:15:17 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:15:21:15:26 | call to params | semmle.label | call to params |
| unicode_normalization.rb:15:21:15:42 | ...[...] | semmle.label | ...[...] |
| unicode_normalization.rb:15:21:15:42 | ...[...] | semmle.label | ...[...] |
| unicode_normalization.rb:16:5:16:23 | unicode_input_manip | semmle.label | unicode_input_manip |
| unicode_normalization.rb:16:27:16:39 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:16:27:16:39 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:16:27:16:59 | call to sub | semmle.label | call to sub |
| unicode_normalization.rb:17:23:17:41 | unicode_input_manip | semmle.label | unicode_input_manip |
| unicode_normalization.rb:18:22:18:40 | unicode_input_manip | semmle.label | unicode_input_manip |
| unicode_normalization.rb:24:5:24:17 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:24:21:24:26 | call to params | semmle.label | call to params |
| unicode_normalization.rb:24:21:24:42 | ...[...] | semmle.label | ...[...] |
| unicode_normalization.rb:25:5:25:21 | unicode_html_safe | semmle.label | unicode_html_safe |
| unicode_normalization.rb:25:25:25:50 | call to html_escape | semmle.label | call to html_escape |
| unicode_normalization.rb:25:37:25:49 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:26:23:26:39 | unicode_html_safe | semmle.label | unicode_html_safe |
| unicode_normalization.rb:27:22:27:38 | unicode_html_safe | semmle.label | unicode_html_safe |
| unicode_normalization.rb:33:5:33:17 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:33:21:33:26 | call to params | semmle.label | call to params |
| unicode_normalization.rb:33:21:33:42 | ...[...] | semmle.label | ...[...] |
| unicode_normalization.rb:34:5:34:21 | unicode_html_safe | semmle.label | unicode_html_safe |
| unicode_normalization.rb:34:25:34:53 | call to escapeHTML | semmle.label | call to escapeHTML |
| unicode_normalization.rb:34:25:34:63 | call to html_safe | semmle.label | call to html_safe |
| unicode_normalization.rb:34:40:34:52 | unicode_input | semmle.label | unicode_input |
| unicode_normalization.rb:35:23:35:39 | unicode_html_safe | semmle.label | unicode_html_safe |
| unicode_normalization.rb:36:22:36:38 | unicode_html_safe | semmle.label | unicode_html_safe |
subpaths
#select
| unicode_normalization.rb:8:23:8:35 | unicode_input | unicode_normalization.rb:7:21:7:26 | call to params | unicode_normalization.rb:8:23:8:35 | unicode_input | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:8:23:8:35 | unicode_input | Unicode transformation (Unicode normalization) | unicode_normalization.rb:7:21:7:26 | call to params | remote user-controlled data |
| unicode_normalization.rb:9:22:9:34 | unicode_input | unicode_normalization.rb:7:21:7:26 | call to params | unicode_normalization.rb:9:22:9:34 | unicode_input | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:9:22:9:34 | unicode_input | Unicode transformation (Unicode normalization) | unicode_normalization.rb:7:21:7:26 | call to params | remote user-controlled data |
| unicode_normalization.rb:17:23:17:41 | unicode_input_manip | unicode_normalization.rb:15:21:15:26 | call to params | unicode_normalization.rb:17:23:17:41 | unicode_input_manip | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:17:23:17:41 | unicode_input_manip | Unicode transformation (Unicode normalization) | unicode_normalization.rb:15:21:15:26 | call to params | remote user-controlled data |
| unicode_normalization.rb:18:22:18:40 | unicode_input_manip | unicode_normalization.rb:15:21:15:26 | call to params | unicode_normalization.rb:18:22:18:40 | unicode_input_manip | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:18:22:18:40 | unicode_input_manip | Unicode transformation (Unicode normalization) | unicode_normalization.rb:15:21:15:26 | call to params | remote user-controlled data |
| unicode_normalization.rb:26:23:26:39 | unicode_html_safe | unicode_normalization.rb:24:21:24:26 | call to params | unicode_normalization.rb:26:23:26:39 | unicode_html_safe | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:26:23:26:39 | unicode_html_safe | Unicode transformation (Unicode normalization) | unicode_normalization.rb:24:21:24:26 | call to params | remote user-controlled data |
| unicode_normalization.rb:27:22:27:38 | unicode_html_safe | unicode_normalization.rb:24:21:24:26 | call to params | unicode_normalization.rb:27:22:27:38 | unicode_html_safe | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:27:22:27:38 | unicode_html_safe | Unicode transformation (Unicode normalization) | unicode_normalization.rb:24:21:24:26 | call to params | remote user-controlled data |
| unicode_normalization.rb:35:23:35:39 | unicode_html_safe | unicode_normalization.rb:33:21:33:26 | call to params | unicode_normalization.rb:35:23:35:39 | unicode_html_safe | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:35:23:35:39 | unicode_html_safe | Unicode transformation (Unicode normalization) | unicode_normalization.rb:33:21:33:26 | call to params | remote user-controlled data |
| unicode_normalization.rb:36:22:36:38 | unicode_html_safe | unicode_normalization.rb:33:21:33:26 | call to params | unicode_normalization.rb:36:22:36:38 | unicode_html_safe | This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters. | unicode_normalization.rb:36:22:36:38 | unicode_html_safe | Unicode transformation (Unicode normalization) | unicode_normalization.rb:33:21:33:26 | call to params | remote user-controlled data |

View File

@@ -0,0 +1 @@
experimental/cwe-176/UnicodeBypassValidation.ql

View File

@@ -0,0 +1,38 @@
require "erb"
include ERB::Util
require 'cgi'
class UnicodeNormalizationOKController < ActionController::Base
def unicodeNormalize
unicode_input = params[:unicode_input]
normalized_nfkc = unicode_input.unicode_normalize(:nfkc) # $MISSING:result=OK
normalized_nfc = unicode_input.unicode_normalize(:nfc) # $MISSING:result=OK
end
end
class UnicodeNormalizationStrManipulationController < ActionController::Base
def unicodeNormalize
unicode_input = params[:unicode_input]
unicode_input_manip = unicode_input.sub(/[aeiou]/, "*")
normalized_nfkc = unicode_input_manip.unicode_normalize(:nfkc) # $result=BAD
normalized_nfc = unicode_input_manip.unicode_normalize(:nfc) # $result=BAD
end
end
class UnicodeNormalizationHtMLEscapeController < ActionController::Base
def unicodeNormalize
unicode_input = params[:unicode_input]
unicode_html_safe = html_escape(unicode_input)
normalized_nfkc = unicode_html_safe.unicode_normalize(:nfkc) # $result=BAD
normalized_nfc = unicode_html_safe.unicode_normalize(:nfc) # $result=BAD
end
end
class UnicodeNormalizationCGIHtMLEscapeController < ActionController::Base
def unicodeNormalize
unicode_input = params[:unicode_input]
unicode_html_safe = CGI.escapeHTML(unicode_input).html_safe
normalized_nfkc = unicode_html_safe.unicode_normalize(:nfkd) # $result=BAD
normalized_nfc = unicode_html_safe.unicode_normalize(:nfd) # $result=BAD
end
end

View File

@@ -1,4 +1,5 @@
failures
testFailures
| improper_memoization.rb:100:1:104:3 | m14 | Unexpected result: result=BAD |
#select
| improper_memoization.rb:50:1:55:3 | m7 | improper_memoization.rb:50:8:50:10 | arg | improper_memoization.rb:51:3:53:5 | ... \|\|= ... |

View File

@@ -2,12 +2,10 @@ import codeql.ruby.AST
import TestUtilities.InlineExpectationsTest
import codeql.ruby.security.ImproperMemoizationQuery
class ImproperMemoizationTest extends InlineExpectationsTest {
ImproperMemoizationTest() { this = "ImproperMemoizationTest" }
module ImproperMemoizationTest implements TestSig {
string getARelevantTag() { result = "result" }
override string getARelevantTag() { result = "result" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "result" and
value = "BAD" and
exists(Expr e |
@@ -18,6 +16,8 @@ class ImproperMemoizationTest extends InlineExpectationsTest {
}
}
import MakeTest<ImproperMemoizationTest>
from Method m, Parameter p, AssignLogicalOrExpr s
where isImproperMemoizationMethod(m, p, s)
select m, p, s

View File

@@ -1,9 +1,8 @@
edges
| app/controllers/foo/stores_controller.rb:8:5:8:6 | dt | app/controllers/foo/stores_controller.rb:9:22:9:23 | dt |
| app/controllers/foo/stores_controller.rb:8:5:8:6 | dt | app/controllers/foo/stores_controller.rb:13:55:13:56 | dt |
| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | app/controllers/foo/stores_controller.rb:8:5:8:6 | dt |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt | app/controllers/foo/stores_controller.rb:13:55:13:56 | dt |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt | app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text |
| app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt | app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt | app/views/foo/stores/show.html.erb:5:9:5:21 | call to local_assigns [element :display_text] |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt | app/views/foo/stores/show.html.erb:9:9:9:21 | call to local_assigns [element :display_text] |
@@ -22,7 +21,6 @@ nodes
| app/controllers/foo/stores_controller.rb:8:5:8:6 | dt | semmle.label | dt |
| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | semmle.label | call to read |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt | semmle.label | dt |
| app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | semmle.label | call to raw_name |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt | semmle.label | dt |
| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | semmle.label | call to display_text |
| app/views/foo/bars/_widget.html.erb:8:9:8:21 | call to local_assigns [element :display_text] | semmle.label | call to local_assigns [element :display_text] |
@@ -39,11 +37,7 @@ nodes
| app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... | semmle.label | ... + ... |
| app/views/foo/stores/show.html.erb:40:76:40:87 | call to display_text | semmle.label | call to display_text |
| app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | semmle.label | call to handle |
| app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | semmle.label | call to raw_name |
| app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | semmle.label | call to handle |
| app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | semmle.label | call to raw_name |
| app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | semmle.label | call to display_name |
| app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name | semmle.label | @other_user_raw_name |
| app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | semmle.label | call to sprintf |
| app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle | semmle.label | call to handle |
subpaths
@@ -57,9 +51,5 @@ subpaths
| app/views/foo/stores/show.html.erb:32:3:32:14 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | app/views/foo/stores/show.html.erb:32:3:32:14 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | stored value |
| app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | stored value |
| app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | stored value |
| app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle | app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle | stored value |

View File

@@ -63,7 +63,7 @@
some_user.handle.html_safe
%>
<%# BAD: Indirect to a database value without escaping %>
<%# BAD: Indirect to a database value without escaping (currently missed due to lack of 'self' handling in ORM tracking) %>
<%=
some_user = User.find 1
some_user.raw_name.html_safe
@@ -75,10 +75,10 @@
some_user.handle
%>
<%# BAD: Indirect to a database value without escaping %>
<%# BAD: Indirect to a database value without escaping (currently missed due to lack of 'self' handling in ORM tracking) %>
<%= @user.display_name.html_safe %>
<%# BAD: Indirect to a database value without escaping %>
<%# BAD: Indirect to a database value without escaping (currently missed due to lack of 'self' handling in ORM tracking) %>
<%= @other_user_raw_name.html_safe %>
<%# BAD: Kernel.sprintf is a taint-step %>

Some files were not shown because too many files have changed in this diff Show More