From eb71b1d1e812a9136820ed126ddfa50d57fb2d91 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Thu, 4 Jan 2024 12:31:13 +0000 Subject: [PATCH 1/9] Add test for erb flow --- .../ql/test/library-tests/dataflow/erb/erb.expected | 5 +++++ ruby/ql/test/library-tests/dataflow/erb/erb.ql | 13 +++++++++++++ ruby/ql/test/library-tests/dataflow/erb/main.rb | 7 +++++++ ruby/ql/test/library-tests/dataflow/erb/view.erb | 1 + ruby/ql/test/library-tests/dataflow/erb/view.rb | 9 +++++++++ 5 files changed, 35 insertions(+) create mode 100644 ruby/ql/test/library-tests/dataflow/erb/erb.expected create mode 100644 ruby/ql/test/library-tests/dataflow/erb/erb.ql create mode 100644 ruby/ql/test/library-tests/dataflow/erb/main.rb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view.erb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view.rb diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.expected b/ruby/ql/test/library-tests/dataflow/erb/erb.expected new file mode 100644 index 000000000000..cf6472ea6def --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.expected @@ -0,0 +1,5 @@ +testFailures +edges +nodes +subpaths +#select diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.ql b/ruby/ql/test/library-tests/dataflow/erb/erb.ql new file mode 100644 index 000000000000..ffa56c6a80d2 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.ql @@ -0,0 +1,13 @@ +/** + * @kind path-problem + */ + +import codeql.ruby.AST +import codeql.ruby.CFG +import TestUtilities.InlineFlowTest +import ValueFlowTest +import ValueFlow::PathGraph + +from ValueFlow::PathNode source, ValueFlow::PathNode sink +where ValueFlow::flowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/main.rb b/ruby/ql/test/library-tests/dataflow/erb/main.rb new file mode 100644 index 000000000000..f8ebb386d9be --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/main.rb @@ -0,0 +1,7 @@ +class App + def run + x = source(1) + view = View.new(x) + render(view) + end +end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/view.erb b/ruby/ql/test/library-tests/dataflow/erb/view.erb new file mode 100644 index 000000000000..383ed98b083f --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view.erb @@ -0,0 +1 @@ +<%= foo() %> \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/view.rb b/ruby/ql/test/library-tests/dataflow/erb/view.rb new file mode 100644 index 000000000000..18bcc69df2d7 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view.rb @@ -0,0 +1,9 @@ +class View + def initialize(x) + @x = x + end + + def foo + sink(@x) # $ hasValueFlow=1 + end +end \ No newline at end of file From efab388eda498b4166ad5797cd65de9e334d6792 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Tue, 16 Jan 2024 11:34:58 +0000 Subject: [PATCH 2/9] Add WIP query for erb flow --- .../library-tests/dataflow/erb/erb.expected | 2 +- .../ql/test/library-tests/dataflow/erb/erb.ql | 63 ++++++++++++++++--- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.expected b/ruby/ql/test/library-tests/dataflow/erb/erb.expected index cf6472ea6def..adb6df738c48 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/erb.expected +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.expected @@ -2,4 +2,4 @@ testFailures edges nodes subpaths -#select +#select \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.ql b/ruby/ql/test/library-tests/dataflow/erb/erb.ql index ffa56c6a80d2..18d1664362b6 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/erb.ql +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.ql @@ -1,13 +1,56 @@ -/** - * @kind path-problem - */ - import codeql.ruby.AST import codeql.ruby.CFG -import TestUtilities.InlineFlowTest -import ValueFlowTest -import ValueFlow::PathGraph +import ruby +import codeql.ruby.DataFlow +import codeql.ruby.AST +import codeql.ruby.TaintTracking +import codeql.ruby.frameworks.data.internal.ApiGraphModels +import codeql.ruby.ApiGraphs +import codeql.ruby.dataflow.RemoteFlowSources +private import codeql.ruby.CFG +private import codeql.ruby.dataflow.BarrierGuards +import codeql.ruby.ast.internal.Module +import codeql.ruby.dataflow.internal.DataFlowPrivate +import codeql.ruby.dataflow.SSA + +from ErbFlow::PartialPathNode source, ErbFlow::PartialPathNode sink +where ErbFlow::partialFlow(source, sink, _) +select source, sink + +module ErbFlow = TaintTracking::Global::FlowExplorationFwd; + +module Erb implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.(DataFlow::CallNode).getMethodName() = "source" } + + predicate isSink(DataFlow::Node node) { + node = any(DataFlow::CallNode c | c.getMethodName() = "sink").getArgument(_) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + isFlowFromViewSelfToTemplate(node1, node2) + } +} + +int explorationLimit() { result = 10 } + +predicate isFlowFromViewSelfToTemplate(DataFlow::Node node1, SsaSelfDefinitionNode node2) { + exists(DataFlow::CallNode call, DataFlow::ClassNode view | + call.getMethodName() = "render" and + call.getArgument(0) = node1 and + view.trackInstance().getAValueReachableFromSource() = node1 and + exists(ErbFile template | + view = getTemplateAssociatedViewClass(template) and node2.getLocation().getFile() = template + ) and + node2.getSelfScope() instanceof Toplevel and + node2.getDefinitionExt() instanceof Ssa::SelfDefinition + ) +} -from ValueFlow::PathNode source, ValueFlow::PathNode sink -where ValueFlow::flowPath(source, sink) -select sink, source, sink, "$@", source, source.toString() \ No newline at end of file +DataFlow::ClassNode getTemplateAssociatedViewClass(ErbFile template) { + // template is in same directory as view + exists(File viewFile | viewFile = result.getADeclaration().getFile() | + template.getParentContainer().getAbsolutePath() = + viewFile.getParentContainer().getAbsolutePath() and + viewFile.getStem() = template.getStem() + ) +} From fc292cfad44557977cc239207af61320b33d515c Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Tue, 16 Jan 2024 11:39:43 +0000 Subject: [PATCH 3/9] Update expected file --- .../library-tests/dataflow/erb/erb.expected | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.expected b/ruby/ql/test/library-tests/dataflow/erb/erb.expected index adb6df738c48..1b78ae1f36e8 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/erb.expected +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.expected @@ -1,5 +1,16 @@ -testFailures -edges -nodes -subpaths -#select \ No newline at end of file +| main.rb:3:13:3:21 | call to source | main.rb:3:9:3:9 | x | +| main.rb:3:13:3:21 | call to source | main.rb:3:9:3:21 | ... = ... | +| main.rb:3:13:3:21 | call to source | main.rb:4:9:4:12 | view [@x] | +| main.rb:3:13:3:21 | call to source | main.rb:4:9:4:26 | ... = ... [@x] | +| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:26 | call to new [@x] | +| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:26 | synthetic splat argument [splat position 0] | +| main.rb:3:13:3:21 | call to source | main.rb:4:25:4:25 | x | +| main.rb:3:13:3:21 | call to source | main.rb:5:9:5:20 | synthetic splat argument [splat position 0, ... (2)] | +| main.rb:3:13:3:21 | call to source | main.rb:5:16:5:19 | view [@x] | +| main.rb:3:13:3:21 | call to source | main.rb:5:16:5:19 | view [Ext] [@x] | +| main.rb:3:13:3:21 | call to source | view.rb:2:5:4:7 | synthetic splat parameter [splat position 0] | +| main.rb:3:13:3:21 | call to source | view.rb:2:20:2:20 | x | +| main.rb:3:13:3:21 | call to source | view.rb:2:20:2:20 | x | +| main.rb:3:13:3:21 | call to source | view.rb:3:9:3:10 | [post] self [@x] | +| main.rb:3:13:3:21 | call to source | view.rb:3:9:3:14 | ... = ... | +| main.rb:3:13:3:21 | call to source | view.rb:3:14:3:14 | x | From a3a8af60a76867d535f1885bb9cbd71fc6d2d9f8 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Wed, 17 Jan 2024 10:51:32 +0000 Subject: [PATCH 4/9] Ruby: Add basic modeling for ViewComponent --- ruby/ql/lib/codeql/ruby/Frameworks.qll | 1 + .../codeql/ruby/frameworks/ViewComponent.qll | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll index df8486824851..225db19dab50 100644 --- a/ruby/ql/lib/codeql/ruby/Frameworks.qll +++ b/ruby/ql/lib/codeql/ruby/Frameworks.qll @@ -38,3 +38,4 @@ private import codeql.ruby.frameworks.Yaml private import codeql.ruby.frameworks.Sequel private import codeql.ruby.frameworks.Ldap private import codeql.ruby.frameworks.Jwt +private import codeql.ruby.frameworks.ViewComponent diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll b/ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll new file mode 100644 index 000000000000..bc2d65a4280e --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll @@ -0,0 +1,41 @@ +private import codeql.ruby.AST +private import codeql.ruby.DataFlow +private import codeql.ruby.dataflow.SSA +private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate + +/** + * Provides modeling for the `view_component` gem. + */ +module ViewComponent { + /** + * A subclass of `ViewComponent::Base`. + */ + class ComponentClass extends DataFlow::ClassNode { + ComponentClass() { + this = DataFlow::getConstant("ViewComponent").getConstant("Base").getADescendentModule() + } + + /** + * Returns the template file for this component. + */ + ErbFile getTemplate() { + result.getAbsolutePath() = + this.getLocation().getFile().getAbsolutePath().replaceAll(".rb", ".html.erb") + } + } + + /** + * An additional jump step from a `ComponentClass` passed as an argument in a call to `render` + * to the `self` variable in its corresponding template. + */ + private predicate jumpStep(DataFlow::Node node1, DataFlowPrivate::SsaSelfDefinitionNode node2) { + exists(DataFlow::CallNode call, ComponentClass component | + call.getMethodName() = "render" and + call.getArgument(0) = node1 and + component.trackInstance().getAValueReachableFromSource() = node1 and + node2.getLocation().getFile() = component.getTemplate() and + node2.getSelfScope() instanceof Toplevel and + node2.getDefinitionExt() instanceof Ssa::SelfDefinition + ) + } +} From c26fbab773f479d5ab484e665089b4212e0a94e5 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 17 Jan 2024 09:51:45 +0100 Subject: [PATCH 5/9] Add more tests --- .../library-tests/dataflow/erb/erb.expected | 38 +++++++++++++------ .../test/library-tests/dataflow/erb/main.rb | 18 +++++++-- .../test/library-tests/dataflow/erb/view.erb | 1 - .../test/library-tests/dataflow/erb/view.rb | 9 ----- .../library-tests/dataflow/erb/view1.html.erb | 8 ++++ .../test/library-tests/dataflow/erb/view1.rb | 16 ++++++++ .../library-tests/dataflow/erb/view2.html.erb | 4 ++ .../test/library-tests/dataflow/erb/view2.rb | 9 +++++ .../library-tests/dataflow/erb/view3.html.erb | 4 ++ .../test/library-tests/dataflow/erb/view3.rb | 9 +++++ 10 files changed, 92 insertions(+), 24 deletions(-) delete mode 100644 ruby/ql/test/library-tests/dataflow/erb/view.erb delete mode 100644 ruby/ql/test/library-tests/dataflow/erb/view.rb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view1.html.erb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view1.rb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view2.html.erb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view2.rb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view3.html.erb create mode 100644 ruby/ql/test/library-tests/dataflow/erb/view3.rb diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.expected b/ruby/ql/test/library-tests/dataflow/erb/erb.expected index 1b78ae1f36e8..becb867f93fc 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/erb.expected +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.expected @@ -1,16 +1,32 @@ | main.rb:3:13:3:21 | call to source | main.rb:3:9:3:9 | x | | main.rb:3:13:3:21 | call to source | main.rb:3:9:3:21 | ... = ... | | main.rb:3:13:3:21 | call to source | main.rb:4:9:4:12 | view [@x] | -| main.rb:3:13:3:21 | call to source | main.rb:4:9:4:26 | ... = ... [@x] | -| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:26 | call to new [@x] | -| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:26 | synthetic splat argument [splat position 0] | -| main.rb:3:13:3:21 | call to source | main.rb:4:25:4:25 | x | +| main.rb:3:13:3:21 | call to source | main.rb:4:9:4:27 | ... = ... [@x] | +| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:27 | call to new [@x] | +| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:27 | synthetic splat argument [splat position 0] | +| main.rb:3:13:3:21 | call to source | main.rb:4:26:4:26 | x | | main.rb:3:13:3:21 | call to source | main.rb:5:9:5:20 | synthetic splat argument [splat position 0, ... (2)] | | main.rb:3:13:3:21 | call to source | main.rb:5:16:5:19 | view [@x] | -| main.rb:3:13:3:21 | call to source | main.rb:5:16:5:19 | view [Ext] [@x] | -| main.rb:3:13:3:21 | call to source | view.rb:2:5:4:7 | synthetic splat parameter [splat position 0] | -| main.rb:3:13:3:21 | call to source | view.rb:2:20:2:20 | x | -| main.rb:3:13:3:21 | call to source | view.rb:2:20:2:20 | x | -| main.rb:3:13:3:21 | call to source | view.rb:3:9:3:10 | [post] self [@x] | -| main.rb:3:13:3:21 | call to source | view.rb:3:9:3:14 | ... = ... | -| main.rb:3:13:3:21 | call to source | view.rb:3:14:3:14 | x | +| main.rb:3:13:3:21 | call to source | view1.rb:5:5:7:7 | synthetic splat parameter [splat position 0] | +| main.rb:3:13:3:21 | call to source | view1.rb:5:20:5:20 | x | +| main.rb:3:13:3:21 | call to source | view1.rb:5:20:5:20 | x | +| main.rb:3:13:3:21 | call to source | view1.rb:6:9:6:10 | [post] self [@x] | +| main.rb:3:13:3:21 | call to source | view1.rb:6:9:6:14 | ... = ... | +| main.rb:3:13:3:21 | call to source | view1.rb:6:14:6:14 | x | +| main.rb:15:13:15:21 | call to source | main.rb:15:9:15:9 | x | +| main.rb:15:13:15:21 | call to source | main.rb:15:9:15:21 | ... = ... | +| main.rb:15:13:15:21 | call to source | main.rb:16:9:16:12 | view [@x] | +| main.rb:15:13:15:21 | call to source | main.rb:16:9:16:27 | ... = ... [@x] | +| main.rb:15:13:15:21 | call to source | main.rb:16:16:16:27 | call to new [@x] | +| main.rb:15:13:15:21 | call to source | main.rb:16:16:16:27 | synthetic splat argument [splat position 0] | +| main.rb:15:13:15:21 | call to source | main.rb:16:26:16:26 | x | +| main.rb:15:13:15:21 | call to source | main.rb:17:9:17:20 | synthetic splat argument [splat position 0, ... (2)] | +| main.rb:15:13:15:21 | call to source | main.rb:17:16:17:19 | view [@x] | +| main.rb:15:13:15:21 | call to source | view3.rb:2:5:4:7 | synthetic splat parameter [splat position 0] | +| main.rb:15:13:15:21 | call to source | view3.rb:2:20:2:20 | x | +| main.rb:15:13:15:21 | call to source | view3.rb:2:20:2:20 | x | +| main.rb:15:13:15:21 | call to source | view3.rb:3:9:3:10 | [post] self [@x] | +| main.rb:15:13:15:21 | call to source | view3.rb:3:9:3:14 | ... = ... | +| main.rb:15:13:15:21 | call to source | view3.rb:3:14:3:14 | x | +| view1.html.erb:6:5:6:13 | call to source | view1.html.erb:6:1:6:14 | synthetic splat argument [splat position 0] | +| view2.html.erb:3:5:3:13 | call to source | view2.html.erb:3:1:3:14 | synthetic splat argument [splat position 0] | diff --git a/ruby/ql/test/library-tests/dataflow/erb/main.rb b/ruby/ql/test/library-tests/dataflow/erb/main.rb index f8ebb386d9be..84af8820399e 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/main.rb +++ b/ruby/ql/test/library-tests/dataflow/erb/main.rb @@ -1,7 +1,19 @@ class App - def run + def run1 x = source(1) - view = View.new(x) + view = View1.new(x) render(view) end -end \ No newline at end of file + + def run2 + view = View2.new + render(view) + view.foo + end + + def run3 + x = source(4) + view = View3.new(x) + render(view) + end +end diff --git a/ruby/ql/test/library-tests/dataflow/erb/view.erb b/ruby/ql/test/library-tests/dataflow/erb/view.erb deleted file mode 100644 index 383ed98b083f..000000000000 --- a/ruby/ql/test/library-tests/dataflow/erb/view.erb +++ /dev/null @@ -1 +0,0 @@ -<%= foo() %> \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/view.rb b/ruby/ql/test/library-tests/dataflow/erb/view.rb deleted file mode 100644 index 18bcc69df2d7..000000000000 --- a/ruby/ql/test/library-tests/dataflow/erb/view.rb +++ /dev/null @@ -1,9 +0,0 @@ -class View - def initialize(x) - @x = x - end - - def foo - sink(@x) # $ hasValueFlow=1 - end -end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/view1.html.erb b/ruby/ql/test/library-tests/dataflow/erb/view1.html.erb new file mode 100644 index 000000000000..606fca45662e --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view1.html.erb @@ -0,0 +1,8 @@ +<%# Flow through an ERB template %> +<%= foo() %> + +<%# Flow out of an ERB template %> +<% +set(source(2)) +foo() +%> diff --git a/ruby/ql/test/library-tests/dataflow/erb/view1.rb b/ruby/ql/test/library-tests/dataflow/erb/view1.rb new file mode 100644 index 000000000000..d0c6a08dd8ff --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view1.rb @@ -0,0 +1,16 @@ +class ViewComponent::Base +end + +class View1 < ViewComponent::Base + def initialize(x) + @x = x + end + + def foo + sink(@x) # $ hasValueFlow=1 $ hasValueFlow=2 + end + + def set(x) + @x = x + end +end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/view2.html.erb b/ruby/ql/test/library-tests/dataflow/erb/view2.html.erb new file mode 100644 index 000000000000..00d2e6f9caa9 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view2.html.erb @@ -0,0 +1,4 @@ +<%# Flow out of an ERB template (side-effect) %> +<% +set(source(3)) +%> diff --git a/ruby/ql/test/library-tests/dataflow/erb/view2.rb b/ruby/ql/test/library-tests/dataflow/erb/view2.rb new file mode 100644 index 000000000000..63d71ebf9fed --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view2.rb @@ -0,0 +1,9 @@ +class View2 < ViewComponent::Base + def foo + sink(@x) # $ hasValueFlow=3 + end + + def set(x) + @x = x + end +end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/dataflow/erb/view3.html.erb b/ruby/ql/test/library-tests/dataflow/erb/view3.html.erb new file mode 100644 index 000000000000..111715016d4c --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view3.html.erb @@ -0,0 +1,4 @@ +<%# Flow into an ERB template %> +<% +sink(get) # $ hasValueFlow=4 +%> diff --git a/ruby/ql/test/library-tests/dataflow/erb/view3.rb b/ruby/ql/test/library-tests/dataflow/erb/view3.rb new file mode 100644 index 000000000000..7a3de851e019 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/erb/view3.rb @@ -0,0 +1,9 @@ +class View3 < ViewComponent::Base + def initialize(x) + @x = x + end + + def get + @x + end +end \ No newline at end of file From 93ab7b5e06337a3cefe9a0b4c84de67e166c7919 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 16 Jan 2024 14:12:48 +0100 Subject: [PATCH 6/9] Ruby: Model flow through `ViewComponent` render methods --- ruby/ql/lib/codeql/ruby/ast/Call.qll | 2 +- .../lib/codeql/ruby/dataflow/FlowSummary.qll | 2 +- .../dataflow/internal/DataFlowDispatch.qll | 330 ++++++++----- .../dataflow/internal/DataFlowPrivate.qll | 134 +++-- .../ruby/dataflow/internal/DataFlowPublic.qll | 4 +- .../codeql/ruby/frameworks/ViewComponent.qll | 34 +- .../ruby/security/CodeInjectionQuery.qll | 4 + .../internal/TypeTrackingImpl.qll | 54 ++- .../library-tests/dataflow/erb/erb.expected | 132 +++-- .../ql/test/library-tests/dataflow/erb/erb.ql | 63 +-- .../dataflow/local/DataflowStep.expected | 1 + .../dataflow/local/TaintStep.expected | 1 + .../dataflow/params/TypeTracker.expected | 457 +++++++++--------- .../type-tracker/TypeTracker.expected | 33 +- 14 files changed, 742 insertions(+), 509 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/ast/Call.qll b/ruby/ql/lib/codeql/ruby/ast/Call.qll index de72b7666242..8a69ebd36fbb 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Call.qll @@ -58,7 +58,7 @@ class Call extends Expr instanceof CallImpl { TCfgScope(result) = viableCallableLambda(c, _) ) or - result = getTarget(this.getAControlFlowNode()) + result = getTarget(TNormalCall(this.getAControlFlowNode())) } override AstNode getAChild(string pred) { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll b/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll index f29876534efc..5940266b07f5 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll @@ -70,7 +70,7 @@ deprecated class RequiredSummaryComponentStack = Impl::Private::RequiredSummaryC */ private module LibraryCallbackSummaries { private predicate libraryCall(CfgNodes::ExprNodes::CallCfgNode call) { - not exists(getTarget(call)) + not exists(getTarget(TNormalCall(call))) } private DataFlow::LocalSourceNode trackLambdaCreation(TypeTracker t) { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll index b757b49e8747..2e491e4fba71 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll @@ -2,7 +2,7 @@ private import codeql.ruby.AST private import codeql.ruby.CFG private import DataFlowPrivate private import codeql.ruby.typetracking.internal.TypeTrackingImpl -private import codeql.ruby.ast.internal.Module +private import codeql.ruby.ast.internal.Module as Module private import FlowSummaryImpl as FlowSummaryImpl private import codeql.ruby.dataflow.FlowSummary private import codeql.ruby.dataflow.SSA @@ -82,23 +82,33 @@ abstract class LibraryCallable extends string { Call getACallSimple() { none() } } +/** A callable defined in library code, which should be taken into account in type tracking. */ +abstract class LibraryCallableToIncludeInTypeTracking extends LibraryCallable { + bindingset[this] + LibraryCallableToIncludeInTypeTracking() { exists(this) } +} + /** * A callable. This includes callables from source code, as well as callables * defined in library code. */ class DataFlowCallable extends TDataFlowCallable { - /** Gets the underlying source code callable, if any. */ - Callable asCallable() { this = TCfgScope(result) } + /** + * Gets the underlying CFG scope, if any. + * + * This is usually a `Callable`, but can also be a `Toplevel` file. + */ + CfgScope asCfgScope() { this = TCfgScope(result) } /** Gets the underlying library callable, if any. */ LibraryCallable asLibraryCallable() { this = TLibraryCallable(result) } /** Gets a textual representation of this callable. */ - string toString() { result = [this.asCallable().toString(), this.asLibraryCallable()] } + string toString() { result = [this.asCfgScope().toString(), this.asLibraryCallable()] } /** Gets the location of this callable. */ Location getLocation() { - result = this.asCallable().getLocation() + result = this.asCfgScope().getLocation() or this instanceof TLibraryCallable and result instanceof EmptyLocation @@ -109,18 +119,18 @@ class DataFlowCallable extends TDataFlowCallable { * A call. This includes calls from source code, as well as call(back)s * inside library callables with a flow summary. */ -class DataFlowCall extends TDataFlowCall { +abstract class DataFlowCall extends TDataFlowCall { /** Gets the enclosing callable. */ - DataFlowCallable getEnclosingCallable() { none() } + abstract DataFlowCallable getEnclosingCallable(); /** Gets the underlying source code call, if any. */ - CfgNodes::ExprNodes::CallCfgNode asCall() { none() } + abstract CfgNodes::ExprNodes::CallCfgNode asCall(); /** Gets a textual representation of this call. */ - string toString() { none() } + abstract string toString(); /** Gets the location of this call. */ - Location getLocation() { none() } + abstract Location getLocation(); /** * Holds if this element is at the specified location. @@ -159,12 +169,14 @@ class SummaryCall extends DataFlowCall, TSummaryCall { override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c } + override CfgNodes::ExprNodes::CallCfgNode asCall() { none() } + override string toString() { result = "[summary] call to " + receiver + " in " + c } override EmptyLocation getLocation() { any() } } -private class NormalCall extends DataFlowCall, TNormalCall { +class NormalCall extends DataFlowCall, TNormalCall { private CfgNodes::ExprNodes::CallCfgNode c; NormalCall() { this = TNormalCall(c) } @@ -178,6 +190,91 @@ private class NormalCall extends DataFlowCall, TNormalCall { override Location getLocation() { result = c.getLocation() } } +/** + * Provides modeling of flow through the `render` method of view components. + * + * ```rb + * # view.rb + * class View < ViewComponent::Base + * def initialize(x) + * @x = x + * end + * + * def foo + * sink(@x) + * end + * end + * ``` + * + * ```erb + * # view.html.erb + * <%= foo() %> # 1 + * ``` + * + * ```rb + * # app.rb + * class App + * def run + * view = View.new(taint) # 2 + * render(view) # 3 + * end + * end + * ``` + * + * The `render` call (3) is modeled using a flow summary. The summary specifies + * that the first argument (`view`) will have a special method invoked on it (we + * call the method `__invoke__toplevel__erb__`), which targets the top-level of the + * matching ERB file (`view.html.erb`). The `view` argument will flow into the receiver + * of the synthesized method call, from there into the implicit `self` parameter of + * the ERB file, and from there to the implicit `self` receiver of the call to `foo` (1). + * + * Since it is not actually possible to specify such flow summaries, we instead + * specify a call-back summary, and adjust the generated call to target the special + * `__invoke__toplevel__erb__` method. + * + * In order to resolve the target of the adjusted method call, we need to take + * the `render` summary into account when constructing the call graph. That is, we + * need to track the `View` instance (2) into the receiver of the adjusted method + * call, in order to figure out that the call target is in fact `view.html.erb`. + */ +private module ViewComponentRenderModeling { + private import codeql.ruby.frameworks.ViewComponent + + private class RenderMethod extends SummarizedCallable, LibraryCallableToIncludeInTypeTracking { + RenderMethod() { this = "render view component" } + + override MethodCall getACallSimple() { result.getMethodName() = "render" } + + override predicate propagatesFlow(string input, string output, boolean preservesValue) { + input = "Argument[0]" and + // use a call-back summary, and adjust it to a method call below + output = "Argument[0].Parameter[self]" and + preservesValue = true + } + } + + private string invokeToplevelName() { result = "__invoke__toplevel__erb__" } + + /** Holds if `call` should be adjusted to be a method call to `name` on `receiver`. */ + predicate adjustedMethodCall(DataFlowCall call, FlowSummaryNode receiver, string name) { + exists(RenderMethod render | + call = TSummaryCall(render, receiver.getSummaryNode()) and + name = invokeToplevelName() + ) + } + + /** Holds if `self` belongs to the top-level of an ERB file with matching view class `view`. */ + pragma[nomagic] + predicate selfInErbToplevel(SelfVariable self, ViewComponent::ComponentClass view) { + self.getDeclaringScope().(Toplevel).getFile() = view.getTemplate() + } + + Toplevel lookupMethod(ViewComponent::ComponentClass m, string name) { + result.getFile() = m.getTemplate() and + name = invokeToplevelName() + } +} + /** A call for which we want to compute call targets. */ private class RelevantCall extends CfgNodes::ExprNodes::CallCfgNode { pragma[nomagic] @@ -188,14 +285,19 @@ private class RelevantCall extends CfgNodes::ExprNodes::CallCfgNode { } pragma[nomagic] -private predicate methodCall(RelevantCall call, DataFlow::Node receiver, string method) { - method = call.getExpr().(MethodCall).getMethodName() and - receiver.asExpr() = call.getReceiver() +private predicate methodCall(DataFlowCall call, DataFlow::Node receiver, string method) { + call.asCall() = + any(RelevantCall rc | + method = rc.getExpr().(MethodCall).getMethodName() and + receiver.asExpr() = rc.getReceiver() + ) + or + ViewComponentRenderModeling::adjustedMethodCall(call, receiver, method) } pragma[nomagic] private predicate flowsToMethodCallReceiver( - RelevantCall call, DataFlow::LocalSourceNode sourceNode, string method + DataFlowCall call, DataFlow::LocalSourceNode sourceNode, string method ) { exists(DataFlow::Node receiver | methodCall(call, receiver, method) and @@ -204,7 +306,7 @@ private predicate flowsToMethodCallReceiver( } pragma[nomagic] -private predicate moduleFlowsToMethodCallReceiver(RelevantCall call, Module m, string method) { +private predicate moduleFlowsToMethodCallReceiver(DataFlowCall call, Module m, string method) { flowsToMethodCallReceiver(call, trackModuleAccess(m), method) } @@ -244,8 +346,11 @@ private predicate selfInMethod(SelfVariable self, MethodBase method, Module m) { /** Holds if `self` belongs to the top-level. */ pragma[nomagic] private predicate selfInToplevel(SelfVariable self, Module m) { + ViewComponentRenderModeling::selfInErbToplevel(self, m) + or + not ViewComponentRenderModeling::selfInErbToplevel(self, _) and self.getDeclaringScope() instanceof Toplevel and - m = TResolved("Object") + m = Module::TResolved("Object") } /** @@ -262,7 +367,7 @@ private predicate selfInToplevel(SelfVariable self, Module m) { */ private predicate asModulePattern(SsaDefinitionExtNode def, Module m) { exists(AsPattern ap | - m = resolveConstantReadAccess(ap.getPattern()) and + m = Module::resolveConstantReadAccess(ap.getPattern()) and def.getDefinitionExt().(Ssa::WriteDefinition).getWriteAccess().getAstNode() = ap.getVariableAccess() ) @@ -286,7 +391,7 @@ private predicate hasAdjacentTypeCheckedReads( exists( CfgNodes::ExprCfgNode pattern, ConditionBlock cb, CfgNodes::ExprNodes::CaseExprCfgNode case | - m = resolveConstantReadAccess(pattern.getExpr()) and + m = Module::resolveConstantReadAccess(pattern.getExpr()) and cb.getLastNode() = pattern and cb.controls(read2.getBasicBlock(), any(SuccessorTypes::MatchingSuccessor match | match.getValue() = true)) and @@ -304,27 +409,27 @@ predicate isUserDefinedNew(SingletonMethod new) { exists(Expr object | singletonMethod(new, "new", object) | selfInModule(object.(SelfVariableReadAccess).getVariable(), _) or - exists(resolveConstantReadAccess(object)) + exists(Module::resolveConstantReadAccess(object)) ) } -private Callable viableSourceCallableNonInit(RelevantCall call) { - result = getTargetInstance(call, _) +private DataFlowCallable viableSourceCallableNonInit(DataFlowCall call) { + result.asCfgScope() = getTargetInstance(call, _) or - result = getTargetSingleton(call, _) + result.asCfgScope() = getTargetSingleton(call, _) or exists(Module cls, string method | - superCall(call, cls, method) and - result = lookupMethod(cls.getAnImmediateAncestor(), method) + superCall(call.asCall(), cls, method) and + result.asCfgScope() = lookupMethod(cls.getAnImmediateAncestor(), method) ) } private Callable viableSourceCallableInit(RelevantCall call) { result = getInitializeTarget(call) } /** Holds if `call` may resolve to the returned source-code method. */ -private Callable viableSourceCallable(RelevantCall call) { +private DataFlowCallable viableSourceCallable(DataFlowCall call) { result = viableSourceCallableNonInit(call) or - result = viableSourceCallableInit(call) + result.asCfgScope() = viableSourceCallableInit(call.asCall()) } /** Holds if `call` may resolve to the returned summarized library method. */ @@ -342,7 +447,7 @@ private predicate extendCall(DataFlow::ExprNode receiver, Module m) { extendCall.getMethodName() = "extend" and exists(DataFlow::LocalSourceNode sourceNode | sourceNode.flowsTo(extendCall.getArgument(_)) | selfInModule(sourceNode.(SelfLocalSourceNode).getVariable(), m) or - m = resolveConstantReadAccess(sourceNode.asExpr().getExpr()) + m = Module::resolveConstantReadAccess(sourceNode.asExpr().getExpr()) ) and receiver = extendCall.getReceiver() ) @@ -355,20 +460,26 @@ private predicate extendCallModule(Module m, Module n) { receiver.flowsTo(e) and extendCall(e, n) | selfInModule(receiver.(SelfLocalSourceNode).getVariable(), m) or - m = resolveConstantReadAccess(receiver.asExpr().getExpr()) + m = Module::resolveConstantReadAccess(receiver.asExpr().getExpr()) ) } +private CfgScope lookupMethod(Module m, string name) { + result = Module::lookupMethod(m, name) + or + result = ViewComponentRenderModeling::lookupMethod(m, name) +} + /** * Gets a method available in module `m`, or in one of `m`'s transitive * sub classes when `exact = false`. */ pragma[nomagic] -private Method lookupMethod(Module m, string name, boolean exact) { +private CfgScope lookupMethod(Module m, string name, boolean exact) { result = lookupMethod(m, name) and exact in [false, true] or - result = lookupMethodInSubClasses(m, name) and + result = Module::lookupMethodInSubClasses(m, name) and exact = false } @@ -405,16 +516,16 @@ private module Cached { } cached - CfgScope getTarget(RelevantCall call) { - result = viableSourceCallableNonInit(call) + CfgScope getTarget(DataFlowCall call) { + result = viableSourceCallableNonInit(call).asCfgScope() or - result = blockCall(call) + result = blockCall(call.asCall()) } /** Gets a viable run-time target for the call `call`. */ cached DataFlowCallable viableCallable(DataFlowCall call) { - result.asCallable() = viableSourceCallable(call.asCall()) + result = viableSourceCallable(call) or result = viableLibraryCallable(call) } @@ -477,14 +588,11 @@ private module Cached { import Cached -pragma[nomagic] -private predicate isNotSelf(DataFlow::Node n) { not n instanceof SelfParameterNodeImpl } - private module TrackModuleInput implements CallGraphConstruction::Simple::InputSig { class State = Module; predicate start(DataFlow::Node start, Module m) { - m = resolveConstantReadAccess(start.asExpr().getExpr()) + m = Module::resolveConstantReadAccess(start.asExpr().getExpr()) } // We exclude steps into `self` parameters, and instead rely on the type of the @@ -511,7 +619,7 @@ private predicate hasUserDefinedNew(Module m) { pragma[nomagic] private predicate isStandardNewCall(RelevantCall new, Module m, boolean exact) { exists(DataFlow::LocalSourceNode sourceNode | - flowsToMethodCallReceiver(new, sourceNode, "new") and + flowsToMethodCallReceiver(TNormalCall(new), sourceNode, "new") and // `m` should not have a user-defined `self.new` method not hasUserDefinedNew(m) | @@ -541,55 +649,55 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig { pragma[nomagic] private predicate isInstanceNoCall(DataFlow::Node n, Module tp, boolean exact) { n.asExpr().getExpr() instanceof NilLiteral and - tp = TResolved("NilClass") and + tp = Module::TResolved("NilClass") and exact = true or n.asExpr().getExpr().(BooleanLiteral).isFalse() and - tp = TResolved("FalseClass") and + tp = Module::TResolved("FalseClass") and exact = true or n.asExpr().getExpr().(BooleanLiteral).isTrue() and - tp = TResolved("TrueClass") and + tp = Module::TResolved("TrueClass") and exact = true or n.asExpr().getExpr() instanceof IntegerLiteral and - tp = TResolved("Integer") and + tp = Module::TResolved("Integer") and exact = true or n.asExpr().getExpr() instanceof FloatLiteral and - tp = TResolved("Float") and + tp = Module::TResolved("Float") and exact = true or n.asExpr().getExpr() instanceof RationalLiteral and - tp = TResolved("Rational") and + tp = Module::TResolved("Rational") and exact = true or n.asExpr().getExpr() instanceof ComplexLiteral and - tp = TResolved("Complex") and + tp = Module::TResolved("Complex") and exact = true or n.asExpr().getExpr() instanceof StringlikeLiteral and - tp = TResolved("String") and + tp = Module::TResolved("String") and exact = true or n.asExpr() instanceof CfgNodes::ExprNodes::ArrayLiteralCfgNode and - tp = TResolved("Array") and + tp = Module::TResolved("Array") and exact = true or n.asExpr() instanceof CfgNodes::ExprNodes::HashLiteralCfgNode and - tp = TResolved("Hash") and + tp = Module::TResolved("Hash") and exact = true or n.asExpr().getExpr() instanceof MethodBase and - tp = TResolved("Symbol") and + tp = Module::TResolved("Symbol") and exact = true or n.asParameter() instanceof BlockParameter and - tp = TResolved("Proc") and + tp = Module::TResolved("Proc") and exact = true or n.asExpr().getExpr() instanceof Lambda and - tp = TResolved("Proc") and + tp = Module::TResolved("Proc") and exact = true or // `self` reference in method or top-level (but not in module or singleton method, @@ -640,11 +748,11 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig { isInstance(start, tp, exact) or exists(Module m | - (if m.isClass() then tp = TResolved("Class") else tp = TResolved("Module")) and + (if m.isClass() then tp = Module::TResolved("Class") else tp = Module::TResolved("Module")) and exact = true | // needed for e.g. `C.new` - m = resolveConstantReadAccess(start.asExpr().getExpr()) + m = Module::resolveConstantReadAccess(start.asExpr().getExpr()) or // needed for e.g. `self.include` selfInModule(start.(SelfLocalSourceNode).getVariable(), m) @@ -657,10 +765,7 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig { pragma[nomagic] predicate stepNoCall(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, StepSummary summary) { - // We exclude steps into `self` parameters. For those, we instead rely on the type of - // the enclosing module - smallStepNoCall(nodeFrom, nodeTo, summary) and - isNotSelf(nodeTo) + smallStepNoCall(nodeFrom, nodeTo, summary) or // We exclude steps into type checked variables. For those, we instead rely on the // type being checked against @@ -692,7 +797,7 @@ private DataFlow::Node trackInstance(Module tp, boolean exact) { } pragma[nomagic] -private Method lookupInstanceMethodCall(RelevantCall call, string method, boolean exact) { +private CfgScope lookupInstanceMethodCall(DataFlowCall call, string method, boolean exact) { exists(Module tp, DataFlow::Node receiver | methodCall(call, pragma[only_bind_into](receiver), pragma[only_bind_into](method)) and receiver = trackInstance(tp, exact) and @@ -707,24 +812,25 @@ private predicate isToplevelMethodInFile(Method m, File f) { } pragma[nomagic] -private CfgScope getTargetInstance(RelevantCall call, string method) { +private CfgScope getTargetInstance(DataFlowCall call, string method) { exists(boolean exact | result = lookupInstanceMethodCall(call, method, exact) and ( if result.(Method).isPrivate() then - call.getReceiver().getExpr() instanceof SelfVariableAccess and + call.asCall().getReceiver().getExpr() instanceof SelfVariableAccess and // For now, we restrict the scope of top-level declarations to their file. // This may remove some plausible targets, but also removes a lot of // implausible targets ( - isToplevelMethodInFile(result, call.getFile()) or + isToplevelMethodInFile(result, call.asCall().getFile()) or not isToplevelMethodInFile(result, _) ) else any() ) and if result.(Method).isProtected() - then result = lookupMethod(call.getExpr().getEnclosingModule().getModule(), method, exact) + then + result = lookupMethod(call.asCall().getExpr().getEnclosingModule().getModule(), method, exact) else any() ) } @@ -801,7 +907,7 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module ) or exists(DataFlow::LocalSourceNode sourceNode | - m = resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and + m = Module::resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and flowsToSingletonMethodObject(sourceNode, method, name) ) or @@ -817,7 +923,7 @@ private MethodBase lookupSingletonMethodDirect(Module m, string name) { or exists(DataFlow::LocalSourceNode sourceNode | sourceNode = trackModuleAccess(m) and - not m = resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and + not m = Module::resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and flowsToSingletonMethodObject(sourceNode, result, name) ) } @@ -843,7 +949,7 @@ private MethodBase lookupSingletonMethodInSubClasses(Module m, string name) { // The 'self' inside such a singleton method could then be any class, leading to self-calls // being resolved to arbitrary singleton methods. // To remedy this, we do not allow following super-classes all the way to Object. - not m = TResolved("Object") and + not m = Module::TResolved("Object") and exists(Module sub | sub.getSuperClass() = m // not `getAnImmediateAncestor` because singleton methods cannot be included | @@ -897,7 +1003,7 @@ predicate singletonMethodOnInstance(MethodBase method, string name, Expr object) singletonMethod(method, name, object) and not selfInModule(object.(SelfVariableReadAccess).getVariable(), _) and // cannot use `trackModuleAccess` because of negative recursion - not exists(resolveConstantReadAccess(object)) + not exists(Module::resolveConstantReadAccess(object)) or exists(DataFlow::ExprNode receiver, Module other | extendCall(receiver, other) and @@ -944,7 +1050,7 @@ private module TrackSingletonMethodOnInstanceInput implements CallGraphConstruct RelevantCall call, DataFlow::Node arg, DataFlow::ParameterNode p, CfgNodes::ExprCfgNode nodeFromPreExpr | - callStep(call, arg, p) and + sourceCallStep(call, arg, p) and nodeTo.getPreUpdateNode() = arg and summary.toString() = "return" and ( @@ -1006,7 +1112,7 @@ private DataFlow::Node trackSingletonMethodOnInstance(MethodBase method, string /** Holds if a `self` access may be the receiver of `call` directly inside module `m`. */ pragma[nomagic] -private predicate selfInModuleFlowsToMethodCallReceiver(RelevantCall call, Module m, string method) { +private predicate selfInModuleFlowsToMethodCallReceiver(DataFlowCall call, Module m, string method) { exists(SelfLocalSourceNode self | flowsToMethodCallReceiver(call, self, method) and selfInModule(self.getVariable(), m) @@ -1019,7 +1125,7 @@ private predicate selfInModuleFlowsToMethodCallReceiver(RelevantCall call, Modul */ pragma[nomagic] private predicate selfInSingletonMethodFlowsToMethodCallReceiver( - RelevantCall call, Module m, string method + DataFlowCall call, Module m, string method ) { exists(SelfLocalSourceNode self, MethodBase caller | flowsToMethodCallReceiver(call, self, method) and @@ -1029,7 +1135,7 @@ private predicate selfInSingletonMethodFlowsToMethodCallReceiver( } pragma[nomagic] -private CfgScope getTargetSingleton(RelevantCall call, string method) { +private CfgScope getTargetSingleton(DataFlowCall call, string method) { // singleton method defined on an instance, e.g. // ```rb // c = C.new @@ -1099,31 +1205,26 @@ private CfgScope getTargetSingleton(RelevantCall call, string method) { */ pragma[nomagic] private predicate argMustFlowToReceiver( - RelevantCall ctx, DataFlow::LocalSourceNode source, DataFlow::Node arg, RelevantCall call, + RelevantCall ctx, DataFlow::LocalSourceNode source, DataFlow::Node arg, DataFlowCall call, string name ) { - exists( - ParameterNodeImpl p, SsaDefinitionExtNode paramDef, ParameterPosition ppos, - ArgumentPosition apos, Callable encl - | + exists(ParameterNodeImpl p, ParameterPosition ppos, ArgumentPosition apos, DataFlowCallable encl | // the receiver of `call` references `p` exists(DataFlow::Node receiver | - LocalFlow::localFlowSsaParamInput(p, paramDef) and - methodCall(pragma[only_bind_into](call), pragma[only_bind_into](receiver), - pragma[only_bind_into](name)) and - receiver.asExpr() = paramDef.getDefinitionExt().(Ssa::Definition).getARead() + methodCall(pragma[only_bind_into](call), pragma[only_bind_into](receiver), name) and + LocalFlow::localMustFlowStep*(p, receiver) ) and // `p` is a parameter of `encl`, - encl = call.getScope() and - p.isParameterOf(TCfgScope(encl), ppos) and + encl = call.getEnclosingCallable() and + p.isParameterOf(encl, ppos) and // `arg` is the argument for `p` in the call `ctx` parameterMatch(ppos, apos) and source.flowsTo(arg) | - encl = viableSourceCallableNonInit(ctx) and + encl = viableSourceCallableNonInit(TNormalCall(ctx)) and arg.(ArgumentNode).sourceArgumentOf(ctx, apos) or - encl = viableSourceCallableInit(ctx) and + encl.asCfgScope() = viableSourceCallableInit(ctx) and if apos.isSelf() then // when we are targeting an initializer, the type of `self` inside the @@ -1131,6 +1232,9 @@ private predicate argMustFlowToReceiver( // of the `new` call arg.asExpr() = ctx else arg.(ArgumentNode).sourceArgumentOf(ctx, apos) + or + ctx.getAstNode() = encl.asLibraryCallable().getACallSimple() and + arg.(ArgumentNode).sourceArgumentOf(ctx, apos) ) } @@ -1146,7 +1250,7 @@ private predicate mayBenefitFromCallContextInitialize( RelevantCall ctx, RelevantCall new, DataFlow::Node arg, Module tp, string name ) { exists(DataFlow::LocalSourceNode source | - argMustFlowToReceiver(ctx, pragma[only_bind_into](source), arg, new, "new") and + argMustFlowToReceiver(ctx, pragma[only_bind_into](source), arg, TNormalCall(new), "new") and source = trackModuleAccess(tp) and name = "initialize" and exists(lookupMethod(tp, name)) @@ -1163,7 +1267,7 @@ private predicate mayBenefitFromCallContextInitialize( */ pragma[nomagic] private predicate mayBenefitFromCallContextInstance( - RelevantCall ctx, RelevantCall call, DataFlow::Node arg, Module tp, boolean exact, string name + RelevantCall ctx, DataFlowCall call, DataFlow::Node arg, Module tp, boolean exact, string name ) { exists(DataFlow::LocalSourceNode source | argMustFlowToReceiver(ctx, pragma[only_bind_into](source), arg, call, @@ -1186,8 +1290,8 @@ private predicate mayBenefitFromCallContextSingleton( RelevantCall ctx, RelevantCall call, DataFlow::Node arg, Module tp, boolean exact, string name ) { exists(DataFlow::LocalSourceNode source | - argMustFlowToReceiver(ctx, pragma[only_bind_into](source), pragma[only_bind_into](arg), call, - pragma[only_bind_into](name)) and + argMustFlowToReceiver(ctx, pragma[only_bind_into](source), pragma[only_bind_into](arg), + TNormalCall(call), pragma[only_bind_into](name)) and exists(lookupSingletonMethod(tp, pragma[only_bind_into](name), exact)) | source = trackModuleAccess(tp) and @@ -1213,7 +1317,7 @@ private predicate mayBenefitFromCallContextSingleton( predicate mayBenefitFromCallContext(DataFlowCall call) { mayBenefitFromCallContextInitialize(_, call.asCall(), _, _, _) or - mayBenefitFromCallContextInstance(_, call.asCall(), _, _, _, _) + mayBenefitFromCallContextInstance(_, call, _, _, _, _) or mayBenefitFromCallContextSingleton(_, call.asCall(), _, _, _, _) } @@ -1227,43 +1331,47 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { mayBenefitFromCallContext(call) and ( // `ctx` can provide a potentially better type bound - exists(RelevantCall call0, Callable res | - call0 = call.asCall() and - res = result.asCallable() and + exists(CfgScope res | + pragma[only_bind_out](res) = result.asCfgScope() and exists(Module m, string name | - mayBenefitFromCallContextInitialize(ctx.asCall(), pragma[only_bind_into](call0), _, - pragma[only_bind_into](m), pragma[only_bind_into](name)) and - res = getInitializeTarget(call0) and - res = lookupMethod(m, name) + exists(RelevantCall call0 | + call0 = call.asCall() and + mayBenefitFromCallContextInitialize(ctx.asCall(), pragma[only_bind_into](call0), _, + pragma[only_bind_into](m), pragma[only_bind_into](name)) and + res = getInitializeTarget(call0) and + res = lookupMethod(m, name) + ) or exists(boolean exact | - mayBenefitFromCallContextInstance(ctx.asCall(), pragma[only_bind_into](call0), _, + mayBenefitFromCallContextInstance(ctx.asCall(), pragma[only_bind_into](call), _, pragma[only_bind_into](m), pragma[only_bind_into](exact), pragma[only_bind_into](name)) and - res = getTargetInstance(call0, name) and + res = getTargetInstance(call, name) and res = lookupMethod(m, name, exact) or - mayBenefitFromCallContextSingleton(ctx.asCall(), pragma[only_bind_into](call0), _, - pragma[only_bind_into](m), pragma[only_bind_into](exact), pragma[only_bind_into](name)) and - res = getTargetSingleton(call0, name) and - res = lookupSingletonMethod(m, name, exact) + exists(RelevantCall call0 | + call0 = call.asCall() and + mayBenefitFromCallContextSingleton(ctx.asCall(), pragma[only_bind_into](call0), _, + pragma[only_bind_into](m), pragma[only_bind_into](exact), pragma[only_bind_into](name)) and + res = getTargetSingleton(call, name) and + res = lookupSingletonMethod(m, name, exact) + ) ) ) ) or // `ctx` cannot provide a type bound, and the receiver of the call is `self`; // in this case, still apply an open-world assumption - exists(RelevantCall call0, RelevantCall ctx0, DataFlow::Node arg, string name | - call0 = call.asCall() and + exists(RelevantCall ctx0, DataFlow::Node arg, string name | ctx0 = ctx.asCall() and - argMustFlowToReceiver(ctx0, _, arg, call0, name) and - not mayBenefitFromCallContextInitialize(ctx0, call0, arg, _, _) and - not mayBenefitFromCallContextInstance(ctx0, call0, arg, _, _, name) and - not mayBenefitFromCallContextSingleton(ctx0, call0, arg, _, _, name) and - result.asCallable() = viableSourceCallable(call0) + argMustFlowToReceiver(ctx0, _, arg, call, name) and + not mayBenefitFromCallContextInitialize(ctx0, call.asCall(), arg, _, _) and + not mayBenefitFromCallContextInstance(ctx0, call, arg, _, _, name) and + not mayBenefitFromCallContextSingleton(ctx0, call.asCall(), arg, _, _, name) and + result = viableSourceCallable(call) ) or // library calls should always be able to resolve - argMustFlowToReceiver(ctx.asCall(), _, _, call.asCall(), _) and + argMustFlowToReceiver(ctx.asCall(), _, _, call, _) and result = viableLibraryCallable(call) ) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 4cc587acaab8..ebe9b1a1b392 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -233,6 +233,38 @@ module LocalFlow { or nodeTo.(BlockArgumentNode).getParameterNode(true) = nodeFrom } + + predicate flowSummaryLocalStep( + FlowSummaryNode nodeFrom, FlowSummaryNode nodeTo, FlowSummaryImpl::Public::SummarizedCallable c + ) { + FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.getSummaryNode(), + nodeTo.getSummaryNode(), true) and + c = nodeFrom.getSummarizedCallable() + } + + predicate localMustFlowStep(Node node1, Node node2) { + LocalFlow::localFlowSsaParamInput(node1, node2) + or + exists(SsaImpl::Definition def | + def.(Ssa::WriteDefinition).assigns(node1.asExpr()) and + node2.(SsaDefinitionExtNode).getDefinitionExt() = def + or + def = node1.(SsaDefinitionExtNode).getDefinitionExt() and + node2.asExpr() = SsaImpl::getARead(def) + ) + or + node1.asExpr() = node2.asExpr().(CfgNodes::ExprNodes::AssignExprCfgNode).getRhs() + or + node1.asExpr() = node2.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue() + or + node1 = node2.(BlockArgumentNode).getParameterNode(true) + or + node1 = + unique(FlowSummaryNode n1 | + FlowSummaryImpl::Private::Steps::summaryLocalStep(n1.getSummaryNode(), + node2.(FlowSummaryNode).getSummaryNode(), true) + ) + } } /** An argument of a call (including qualifier arguments and block arguments). */ @@ -496,7 +528,8 @@ private module Cached { p instanceof HashSplatParameter or p instanceof SplatParameter } or - TSelfParameterNode(MethodBase m) or + TSelfMethodParameterNode(MethodBase m) or + TSelfToplevelParameterNode(Toplevel t) or TLambdaSelfReferenceNode(Callable c) { lambdaCreationExpr(_, _, c) } or TBlockParameterNode(MethodBase m) or TBlockArgumentNode(CfgNodes::ExprNodes::CallCfgNode yield) { @@ -506,11 +539,11 @@ private module Cached { isParameterNode(_, c, any(ParameterPosition p | p.isKeyword(_))) } or TSynthSplatParameterNode(DataFlowCallable c) { - exists(c.asCallable()) and // exclude library callables (for now) + exists(c.asCfgScope()) and // exclude library callables (for now) isParameterNode(_, c, any(ParameterPosition p | p.isPositional(_))) } or TSynthSplatParameterShiftNode(DataFlowCallable c, int splatPos, int n) { - splatPos = unique(int i | splatParameterAt(c.asCallable(), i) and i > 0) and + splatPos = unique(int i | splatParameterAt(c.asCfgScope(), i) and i > 0) and n in [0 .. 10] } or TExprPostUpdateNode(CfgNodes::ExprCfgNode n) { @@ -536,6 +569,8 @@ private module Cached { } or TCaptureNode(VariableCapture::Flow::SynthesizedCaptureNode cn) + class TSelfParameterNode = TSelfMethodParameterNode or TSelfToplevelParameterNode; + class TSourceParameterNode = TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or TSynthHashSplatParameterNode or TSynthSplatParameterNode; @@ -567,8 +602,7 @@ private module Cached { not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _) ) or - FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), - nodeTo.(FlowSummaryNode).getSummaryNode(), true) + LocalFlow::flowSummaryLocalStep(nodeFrom, nodeTo, _) or VariableCapture::valueStep(nodeFrom, nodeTo) } @@ -601,6 +635,8 @@ private module Cached { LocalFlow::localFlowSsaInputFromRead(_, nodeFrom, nodeTo) or VariableCapture::flowInsensitiveStep(nodeFrom, nodeTo) + or + LocalFlow::flowSummaryLocalStep(nodeFrom, nodeTo, any(LibraryCallableToIncludeInTypeTracking c)) } /** Holds if `n` wraps an SSA definition without ingoing flow. */ @@ -713,7 +749,7 @@ private module Cached { cached predicate exprNodeReturnedFromCached(ExprNode e, Callable c) { exists(ReturnNode r | - nodeGetEnclosingCallable(r).asCallable() = c and + nodeGetEnclosingCallable(r).asCfgScope() = c and ( r.(ExplicitReturnNode).getReturningNode().getReturnedValueNode() = e.asExpr() or r.(ExprReturnNode) = e @@ -879,10 +915,10 @@ private module ParameterNodes { abstract predicate isParameterOf(DataFlowCallable c, ParameterPosition pos); - final predicate isSourceParameterOf(Callable c, ParameterPosition pos) { + final predicate isSourceParameterOf(CfgScope c, ParameterPosition pos) { exists(DataFlowCallable callable | this.isParameterOf(callable, pos) and - c = callable.asCallable() + c = callable.asCfgScope() ) } } @@ -899,7 +935,7 @@ private module ParameterNodes { override Parameter getParameter() { result = parameter } override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - exists(Callable callable | callable = c.asCallable() | + exists(Callable callable | callable = c.asCfgScope() | exists(int i | pos.isPositional(i) and callable.getParameter(i) = parameter | parameter instanceof SimpleParameter or @@ -935,32 +971,64 @@ private module ParameterNodes { * The value of the `self` parameter at function entry, viewed as a node in a data * flow graph. */ - class SelfParameterNodeImpl extends ParameterNodeImpl, TSelfParameterNode { + abstract class SelfParameterNodeImpl extends ParameterNodeImpl, TSelfParameterNode { + /** Gets the corresponding SSA `self` definition, if any. */ + abstract Ssa::SelfDefinition getSelfDefinition(); + + /** Gets the underlying `self` variable. */ + abstract SelfVariable getSelfVariable(); + + final override Parameter getParameter() { none() } + + final override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + c = TCfgScope(this.getCfgScope()) and pos.isSelf() + } + + final override string toStringImpl() { result = "self in " + this.getCfgScope() } + } + + /** + * The value of the `self` parameter at method entry, viewed as a node in a data + * flow graph. + */ + class SelfMethodParameterNodeImpl extends SelfParameterNodeImpl, TSelfMethodParameterNode { private MethodBase method; - SelfParameterNodeImpl() { this = TSelfParameterNode(method) } + SelfMethodParameterNodeImpl() { this = TSelfMethodParameterNode(method) } final MethodBase getMethod() { result = method } - /** Gets the corresponding SSA `self` definition, if any. */ - Ssa::SelfDefinition getSelfDefinition() { + override Ssa::SelfDefinition getSelfDefinition() { result.getSourceVariable().getDeclaringScope() = method } - /** Gets the underlying `self` variable. */ - final SelfVariable getSelfVariable() { result.getDeclaringScope() = method } + final override SelfVariable getSelfVariable() { result.getDeclaringScope() = method } - override Parameter getParameter() { none() } + override CfgScope getCfgScope() { result = method } - override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - method = c.asCallable() and pos.isSelf() + override Location getLocationImpl() { result = method.getLocation() } + } + + /** + * The value of the `self` parameter at top-level entry, viewed as a node in a data + * flow graph. + */ + class SelfToplevelParameterNodeImpl extends SelfParameterNodeImpl, TSelfToplevelParameterNode { + private Toplevel t; + + SelfToplevelParameterNodeImpl() { this = TSelfToplevelParameterNode(t) } + + final Toplevel getToplevel() { result = t } + + override Ssa::SelfDefinition getSelfDefinition() { + result.getSourceVariable().getDeclaringScope() = t } - override CfgScope getCfgScope() { result = method } + final override SelfVariable getSelfVariable() { result.getDeclaringScope() = t } - override Location getLocationImpl() { result = method.getLocation() } + override CfgScope getCfgScope() { result = t } - override string toStringImpl() { result = "self in " + method } + override Location getLocationImpl() { result = t.getLocation() } } /** @@ -982,7 +1050,7 @@ private module ParameterNodes { override Parameter getParameter() { none() } override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - callable = c.asCallable() and pos.isLambdaSelf() + callable = c.asCfgScope() and pos.isLambdaSelf() } override CfgScope getCfgScope() { result = callable } @@ -1008,7 +1076,7 @@ private module ParameterNodes { } override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - c.asCallable() = method and pos.isBlock() + c.asCfgScope() = method and pos.isBlock() } CfgNodes::ExprNodes::CallCfgNode getAYieldCall() { @@ -1086,7 +1154,7 @@ private module ParameterNodes { c = callable and pos.isSynthHashSplat() } - final override CfgScope getCfgScope() { result = callable.asCallable() } + final override CfgScope getCfgScope() { result = callable.asCfgScope() } final override DataFlowCallable getEnclosingCallable() { result = callable } @@ -1142,7 +1210,7 @@ private module ParameterNodes { predicate readInto(ParameterNode p, ContentSet c) { exists(int n | isParameterNode(p, callable, any(ParameterPosition pos | pos.isPositional(n))) and - not exists(int i | splatParameterAt(callable.asCallable(), i) and i < n) + not exists(int i | splatParameterAt(callable.asCfgScope(), i) and i < n) | // Important: do not include `TSplatContent(_, false)` here, as normal parameter matching is possible c = getSplatContent(n, true) @@ -1159,7 +1227,7 @@ private module ParameterNodes { c = callable and pos.isSynthSplat() } - final override CfgScope getCfgScope() { result = callable.asCallable() } + final override CfgScope getCfgScope() { result = callable.asCfgScope() } final override DataFlowCallable getEnclosingCallable() { result = callable } @@ -1210,7 +1278,7 @@ private module ParameterNodes { cs = getArrayContent(pos) } - final override CfgScope getCfgScope() { result = callable.asCallable() } + final override CfgScope getCfgScope() { result = callable.asCfgScope() } final override DataFlowCallable getEnclosingCallable() { result = callable } @@ -1319,11 +1387,11 @@ module ArgumentNodes { } private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode { - private SummaryCall call_; + private FlowSummaryImpl::Private::SummaryNode receiver; private ArgumentPosition pos_; SummaryArgumentNode() { - FlowSummaryImpl::Private::summaryArgumentNode(call_.getReceiver(), this.getSummaryNode(), pos_) + FlowSummaryImpl::Private::summaryArgumentNode(receiver, this.getSummaryNode(), pos_) } override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) { @@ -1331,7 +1399,7 @@ module ArgumentNodes { } override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { - call = call_ and pos = pos_ + call.(SummaryCall).getReceiver() = receiver and pos = pos_ } } @@ -1541,7 +1609,7 @@ module ArgumentNodes { import ArgumentNodes /** A call to `new`. */ -private class NewCall extends DataFlowCall { +private class NewCall extends NormalCall { NewCall() { this.asCall().getExpr().(MethodCall).getMethodName() = "new" } } @@ -1854,7 +1922,7 @@ predicate clearsContent(Node n, ContentSet c) { ParameterPosition keywordPos, ConstantValue::ConstantSymbolValue cv, string name | n = TNormalParameterNode(hashSplatParam) and - callable.asCallable() = hashSplatParam.getCallable() and + callable.asCfgScope() = hashSplatParam.getCallable() and keywordParam.isParameterOf(callable, keywordPos) and keywordPos.isKeyword(name) and c.isKnownOrUnknownElement(TKnownElementContent(cv)) and @@ -2040,7 +2108,7 @@ private predicate lambdaCreationExpr(CfgNodes::ExprCfgNode creation, LambdaCallK /** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { - lambdaCreationExpr(creation.asExpr(), kind, c.asCallable()) + lambdaCreationExpr(creation.asExpr(), kind, c.asCfgScope()) } /** Holds if `call` is a call to `lambda`, `proc`, or `Proc.new` */ diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll index afc4ad146119..8d0c565a7376 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll @@ -77,7 +77,7 @@ class Node extends TNode { or exists(DataFlowCallable c | lambdaCreation(this, _, c) and - result.asCallableAstNode() = c.asCallable() + result.asCallableAstNode() = c.asCfgScope() ) } @@ -1067,7 +1067,7 @@ class ModuleNode instanceof Module { * Does not take inheritance into account. */ ParameterNode getAnOwnInstanceSelf() { - result = TSelfParameterNode(this.getAnOwnInstanceMethod().asCallableAstNode()) + result = TSelfMethodParameterNode(this.getAnOwnInstanceMethod().asCallableAstNode()) } /** diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll b/ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll index bc2d65a4280e..5f6272fd2cbf 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ViewComponent.qll @@ -1,7 +1,8 @@ +/** + * Provides modeling for the `view_component` gem. + */ + private import codeql.ruby.AST -private import codeql.ruby.DataFlow -private import codeql.ruby.dataflow.SSA -private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate /** * Provides modeling for the `view_component` gem. @@ -10,32 +11,19 @@ module ViewComponent { /** * A subclass of `ViewComponent::Base`. */ - class ComponentClass extends DataFlow::ClassNode { - ComponentClass() { - this = DataFlow::getConstant("ViewComponent").getConstant("Base").getADescendentModule() - } + class ComponentClass extends Module { + ComponentClass() { this.getAnAncestor().getQualifiedName() = "ViewComponent::Base" } /** * Returns the template file for this component. */ ErbFile getTemplate() { result.getAbsolutePath() = - this.getLocation().getFile().getAbsolutePath().replaceAll(".rb", ".html.erb") + this.getADeclaration() + .getLocation() + .getFile() + .getAbsolutePath() + .replaceAll(".rb", ".html.erb") } } - - /** - * An additional jump step from a `ComponentClass` passed as an argument in a call to `render` - * to the `self` variable in its corresponding template. - */ - private predicate jumpStep(DataFlow::Node node1, DataFlowPrivate::SsaSelfDefinitionNode node2) { - exists(DataFlow::CallNode call, ComponentClass component | - call.getMethodName() = "render" and - call.getArgument(0) = node1 and - component.trackInstance().getAValueReachableFromSource() = node1 and - node2.getLocation().getFile() = component.getTemplate() and - node2.getSelfScope() instanceof Toplevel and - node2.getDefinitionExt() instanceof Ssa::SelfDefinition - ) - } } diff --git a/ruby/ql/lib/codeql/ruby/security/CodeInjectionQuery.qll b/ruby/ql/lib/codeql/ruby/security/CodeInjectionQuery.qll index 58b150d57126..6641bbe2c340 100644 --- a/ruby/ql/lib/codeql/ruby/security/CodeInjectionQuery.qll +++ b/ruby/ql/lib/codeql/ruby/security/CodeInjectionQuery.qll @@ -55,6 +55,10 @@ private module Config implements DataFlow::StateConfigSig { } predicate isBarrier(DataFlow::Node node, FlowState state) { node.(Sanitizer).getAState() = state } + + predicate isBarrierIn(DataFlow::Node node) { node instanceof Source } + + int fieldFlowBranchLimit() { result = 10 } } /** diff --git a/ruby/ql/lib/codeql/ruby/typetracking/internal/TypeTrackingImpl.qll b/ruby/ql/lib/codeql/ruby/typetracking/internal/TypeTrackingImpl.qll index 750c96ef7236..419fcf621b2f 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/internal/TypeTrackingImpl.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/internal/TypeTrackingImpl.qll @@ -28,7 +28,7 @@ private predicate flowThrough(DataFlowPublic::ParameterNode param) { /** Holds if there is flow from `arg` to `p` via the call `call`, not counting `new -> initialize` call steps. */ pragma[nomagic] private predicate callStepNoInitialize( - ExprNodes::CallCfgNode call, DataFlow::Node arg, DataFlowPrivate::ParameterNodeImpl p + DataFlowDispatch::DataFlowCall call, DataFlow::Node arg, DataFlowPrivate::ParameterNodeImpl p ) { exists(DataFlowDispatch::ParameterPosition pos | argumentPositionMatch(call, arg, pos) and @@ -93,7 +93,7 @@ private predicate localFieldStep(DataFlow::Node pred, DataFlow::Node succ) { } pragma[noinline] -private predicate argumentPositionMatch( +private predicate sourceArgumentPositionMatch( ExprNodes::CallCfgNode call, DataFlowPrivate::ArgumentNode arg, DataFlowDispatch::ParameterPosition ppos ) { @@ -104,23 +104,54 @@ private predicate argumentPositionMatch( ) } +pragma[noinline] +private predicate argumentPositionMatch( + DataFlowDispatch::DataFlowCall call, DataFlowPrivate::ArgumentNode arg, + DataFlowDispatch::ParameterPosition ppos +) { + sourceArgumentPositionMatch(call.asCall(), arg, ppos) + or + exists(DataFlowDispatch::ArgumentPosition apos | + DataFlowDispatch::parameterMatch(ppos, apos) and + arg.argumentOf(call, apos) and + call.getEnclosingCallable().asLibraryCallable() instanceof + DataFlowDispatch::LibraryCallableToIncludeInTypeTracking + ) +} + pragma[noinline] private predicate viableParam( - ExprNodes::CallCfgNode call, DataFlowPrivate::ParameterNodeImpl p, + DataFlowDispatch::DataFlowCall call, DataFlowPrivate::ParameterNodeImpl p, DataFlowDispatch::ParameterPosition ppos ) { - exists(Cfg::CfgScope callable | - DataFlowDispatch::getTarget(call) = callable or - DataFlowDispatch::getInitializeTarget(call) = callable + exists(DataFlowDispatch::DataFlowCallable callable | + DataFlowDispatch::getTarget(call) = callable.asCfgScope() or + DataFlowDispatch::getInitializeTarget(call.asCall()) = callable.asCfgScope() or + call.asCall().getAstNode() = + callable + .asLibraryCallable() + .(DataFlowDispatch::LibraryCallableToIncludeInTypeTracking) + .getACallSimple() | - p.isSourceParameterOf(callable, ppos) + p.isParameterOf(callable, ppos) + ) +} + +/** Holds if there is flow from `arg` to `p` via the source-code call `call`. */ +pragma[nomagic] +predicate sourceCallStep( + ExprNodes::CallCfgNode call, DataFlow::Node arg, DataFlowPrivate::ParameterNodeImpl p +) { + exists(DataFlowDispatch::ParameterPosition pos | + sourceArgumentPositionMatch(call, arg, pos) and + viableParam(DataFlowDispatch::TNormalCall(call), p, pos) ) } /** Holds if there is flow from `arg` to `p` via the call `call`. */ pragma[nomagic] predicate callStep( - ExprNodes::CallCfgNode call, DataFlow::Node arg, DataFlowPrivate::ParameterNodeImpl p + DataFlowDispatch::DataFlowCall call, DataFlow::Node arg, DataFlowPrivate::ParameterNodeImpl p ) { exists(DataFlowDispatch::ParameterPosition pos | argumentPositionMatch(call, arg, pos) and @@ -192,7 +223,7 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input { Node argumentOf(Node call, SummaryComponent arg, boolean isPostUpdate) { exists(DataFlowDispatch::ParameterPosition pos, DataFlowPrivate::ArgumentNode n | arg = FlowSummaryImpl::Private::SummaryComponent::argument(pos) and - argumentPositionMatch(call.asExpr(), n, pos) + sourceArgumentPositionMatch(call.asExpr(), n, pos) | isPostUpdate = false and result = n or @@ -272,7 +303,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput { predicate levelStepCall(Node nodeFrom, LocalSourceNode nodeTo) { exists(DataFlowPublic::ParameterNode param | flowThrough(param) and - callStepNoInitialize(nodeTo.asExpr(), nodeFrom, param) + callStepNoInitialize(DataFlowDispatch::TNormalCall(nodeTo.asExpr()), nodeFrom, param) ) } @@ -296,7 +327,8 @@ module TypeTrackingInput implements Shared::TypeTrackingInput { exists(ExprNodes::CallCfgNode call | nodeFrom instanceof DataFlowPrivate::ReturnNode and not nodeFrom instanceof DataFlowPrivate::InitializeReturnNode and - nodeFrom.(DataFlowPrivate::NodeImpl).getCfgScope() = DataFlowDispatch::getTarget(call) and + nodeFrom.(DataFlowPrivate::NodeImpl).getCfgScope() = + DataFlowDispatch::getTarget(DataFlowDispatch::TNormalCall(call)) and // deliberately do not include `getInitializeTarget`, since calls to `new` should not // get the return value from `initialize`. Any fields being set in the initializer // will reach all reads via `callStep` and `localFieldStep`. diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.expected b/ruby/ql/test/library-tests/dataflow/erb/erb.expected index becb867f93fc..1ca2216a5590 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/erb.expected +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.expected @@ -1,32 +1,104 @@ +testFailures +edges +| main.rb:3:9:3:9 | x | main.rb:4:26:4:26 | x | | main.rb:3:13:3:21 | call to source | main.rb:3:9:3:9 | x | -| main.rb:3:13:3:21 | call to source | main.rb:3:9:3:21 | ... = ... | -| main.rb:3:13:3:21 | call to source | main.rb:4:9:4:12 | view [@x] | -| main.rb:3:13:3:21 | call to source | main.rb:4:9:4:27 | ... = ... [@x] | -| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:27 | call to new [@x] | -| main.rb:3:13:3:21 | call to source | main.rb:4:16:4:27 | synthetic splat argument [splat position 0] | -| main.rb:3:13:3:21 | call to source | main.rb:4:26:4:26 | x | -| main.rb:3:13:3:21 | call to source | main.rb:5:9:5:20 | synthetic splat argument [splat position 0, ... (2)] | -| main.rb:3:13:3:21 | call to source | main.rb:5:16:5:19 | view [@x] | -| main.rb:3:13:3:21 | call to source | view1.rb:5:5:7:7 | synthetic splat parameter [splat position 0] | -| main.rb:3:13:3:21 | call to source | view1.rb:5:20:5:20 | x | -| main.rb:3:13:3:21 | call to source | view1.rb:5:20:5:20 | x | -| main.rb:3:13:3:21 | call to source | view1.rb:6:9:6:10 | [post] self [@x] | -| main.rb:3:13:3:21 | call to source | view1.rb:6:9:6:14 | ... = ... | -| main.rb:3:13:3:21 | call to source | view1.rb:6:14:6:14 | x | +| main.rb:4:9:4:12 | view [@x] | main.rb:5:16:5:19 | view [@x] | +| main.rb:4:16:4:27 | call to new [@x] | main.rb:4:9:4:12 | view [@x] | +| main.rb:4:26:4:26 | x | main.rb:4:16:4:27 | call to new [@x] | +| main.rb:4:26:4:26 | x | view1.rb:5:20:5:20 | x | +| main.rb:5:16:5:19 | view [@x] | view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | +| main.rb:10:16:10:19 | [post] view [@x] | main.rb:11:9:11:12 | view [@x] | +| main.rb:11:9:11:12 | view [@x] | view2.rb:2:5:4:7 | self in foo [@x] | +| main.rb:15:9:15:9 | x | main.rb:16:26:16:26 | x | | main.rb:15:13:15:21 | call to source | main.rb:15:9:15:9 | x | -| main.rb:15:13:15:21 | call to source | main.rb:15:9:15:21 | ... = ... | -| main.rb:15:13:15:21 | call to source | main.rb:16:9:16:12 | view [@x] | -| main.rb:15:13:15:21 | call to source | main.rb:16:9:16:27 | ... = ... [@x] | -| main.rb:15:13:15:21 | call to source | main.rb:16:16:16:27 | call to new [@x] | -| main.rb:15:13:15:21 | call to source | main.rb:16:16:16:27 | synthetic splat argument [splat position 0] | -| main.rb:15:13:15:21 | call to source | main.rb:16:26:16:26 | x | -| main.rb:15:13:15:21 | call to source | main.rb:17:9:17:20 | synthetic splat argument [splat position 0, ... (2)] | -| main.rb:15:13:15:21 | call to source | main.rb:17:16:17:19 | view [@x] | -| main.rb:15:13:15:21 | call to source | view3.rb:2:5:4:7 | synthetic splat parameter [splat position 0] | -| main.rb:15:13:15:21 | call to source | view3.rb:2:20:2:20 | x | -| main.rb:15:13:15:21 | call to source | view3.rb:2:20:2:20 | x | -| main.rb:15:13:15:21 | call to source | view3.rb:3:9:3:10 | [post] self [@x] | -| main.rb:15:13:15:21 | call to source | view3.rb:3:9:3:14 | ... = ... | -| main.rb:15:13:15:21 | call to source | view3.rb:3:14:3:14 | x | -| view1.html.erb:6:5:6:13 | call to source | view1.html.erb:6:1:6:14 | synthetic splat argument [splat position 0] | -| view2.html.erb:3:5:3:13 | call to source | view2.html.erb:3:1:3:14 | synthetic splat argument [splat position 0] | +| main.rb:16:9:16:12 | view [@x] | main.rb:17:16:17:19 | view [@x] | +| main.rb:16:16:16:27 | call to new [@x] | main.rb:16:9:16:12 | view [@x] | +| main.rb:16:26:16:26 | x | main.rb:16:16:16:27 | call to new [@x] | +| main.rb:16:26:16:26 | x | view3.rb:2:20:2:20 | x | +| main.rb:17:16:17:19 | view [@x] | view3.html.erb:3:1:4:1 | self in view3.html.erb [@x] | +| view1.html.erb:2:5:2:9 | self [@x] | view1.rb:9:5:11:7 | self in foo [@x] | +| view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | view1.html.erb:2:5:2:9 | self [@x] | +| view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | view1.html.erb:7:1:7:5 | self [@x] | +| view1.html.erb:6:1:6:14 | [post] self [@x] | view1.html.erb:7:1:7:5 | self [@x] | +| view1.html.erb:6:5:6:13 | call to source | view1.html.erb:6:1:6:14 | [post] self [@x] | +| view1.html.erb:6:5:6:13 | call to source | view1.rb:13:13:13:13 | x | +| view1.html.erb:7:1:7:5 | self [@x] | view1.rb:9:5:11:7 | self in foo [@x] | +| view1.html.erb:7:1:7:5 | self [@x] | view1.rb:9:5:11:7 | self in foo [@x] | +| view1.rb:5:20:5:20 | x | view1.rb:6:14:6:14 | x | +| view1.rb:6:14:6:14 | x | view1.rb:6:9:6:10 | [post] self [@x] | +| view1.rb:9:5:11:7 | self in foo [@x] | view1.rb:10:14:10:15 | self [@x] | +| view1.rb:10:14:10:15 | self [@x] | view1.rb:10:14:10:15 | @x | +| view1.rb:13:13:13:13 | x | view1.rb:14:14:14:14 | x | +| view1.rb:14:14:14:14 | x | view1.rb:14:9:14:10 | [post] self [@x] | +| view2.html.erb:3:1:3:14 | [post] self [@x] | main.rb:10:16:10:19 | [post] view [@x] | +| view2.html.erb:3:5:3:13 | call to source | view2.html.erb:3:1:3:14 | [post] self [@x] | +| view2.html.erb:3:5:3:13 | call to source | view2.rb:6:13:6:13 | x | +| view2.rb:2:5:4:7 | self in foo [@x] | view2.rb:3:14:3:15 | self [@x] | +| view2.rb:3:14:3:15 | self [@x] | view2.rb:3:14:3:15 | @x | +| view2.rb:6:13:6:13 | x | view2.rb:7:14:7:14 | x | +| view2.rb:7:14:7:14 | x | view2.rb:7:9:7:10 | [post] self [@x] | +| view3.html.erb:3:1:4:1 | self in view3.html.erb [@x] | view3.html.erb:3:6:3:8 | self [@x] | +| view3.html.erb:3:6:3:8 | self [@x] | view3.html.erb:3:6:3:8 | call to get | +| view3.html.erb:3:6:3:8 | self [@x] | view3.rb:6:5:8:7 | self in get [@x] | +| view3.rb:2:20:2:20 | x | view3.rb:3:14:3:14 | x | +| view3.rb:3:14:3:14 | x | view3.rb:3:9:3:10 | [post] self [@x] | +| view3.rb:6:5:8:7 | self in get [@x] | view3.rb:7:9:7:10 | self [@x] | +| view3.rb:7:9:7:10 | self [@x] | view3.rb:7:9:7:10 | @x | +nodes +| main.rb:3:9:3:9 | x | semmle.label | x | +| main.rb:3:13:3:21 | call to source | semmle.label | call to source | +| main.rb:4:9:4:12 | view [@x] | semmle.label | view [@x] | +| main.rb:4:16:4:27 | call to new [@x] | semmle.label | call to new [@x] | +| main.rb:4:26:4:26 | x | semmle.label | x | +| main.rb:5:16:5:19 | view [@x] | semmle.label | view [@x] | +| main.rb:10:16:10:19 | [post] view [@x] | semmle.label | [post] view [@x] | +| main.rb:11:9:11:12 | view [@x] | semmle.label | view [@x] | +| main.rb:15:9:15:9 | x | semmle.label | x | +| main.rb:15:13:15:21 | call to source | semmle.label | call to source | +| main.rb:16:9:16:12 | view [@x] | semmle.label | view [@x] | +| main.rb:16:16:16:27 | call to new [@x] | semmle.label | call to new [@x] | +| main.rb:16:26:16:26 | x | semmle.label | x | +| main.rb:17:16:17:19 | view [@x] | semmle.label | view [@x] | +| view1.html.erb:2:5:2:9 | self [@x] | semmle.label | self [@x] | +| view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | semmle.label | self in view1.html.erb [@x] | +| view1.html.erb:6:1:6:14 | [post] self [@x] | semmle.label | [post] self [@x] | +| view1.html.erb:6:5:6:13 | call to source | semmle.label | call to source | +| view1.html.erb:7:1:7:5 | self [@x] | semmle.label | self [@x] | +| view1.html.erb:7:1:7:5 | self [@x] | semmle.label | self [@x] | +| view1.rb:5:20:5:20 | x | semmle.label | x | +| view1.rb:6:9:6:10 | [post] self [@x] | semmle.label | [post] self [@x] | +| view1.rb:6:14:6:14 | x | semmle.label | x | +| view1.rb:9:5:11:7 | self in foo [@x] | semmle.label | self in foo [@x] | +| view1.rb:10:14:10:15 | @x | semmle.label | @x | +| view1.rb:10:14:10:15 | self [@x] | semmle.label | self [@x] | +| view1.rb:13:13:13:13 | x | semmle.label | x | +| view1.rb:14:9:14:10 | [post] self [@x] | semmle.label | [post] self [@x] | +| view1.rb:14:14:14:14 | x | semmle.label | x | +| view2.html.erb:3:1:3:14 | [post] self [@x] | semmle.label | [post] self [@x] | +| view2.html.erb:3:5:3:13 | call to source | semmle.label | call to source | +| view2.rb:2:5:4:7 | self in foo [@x] | semmle.label | self in foo [@x] | +| view2.rb:3:14:3:15 | @x | semmle.label | @x | +| view2.rb:3:14:3:15 | self [@x] | semmle.label | self [@x] | +| view2.rb:6:13:6:13 | x | semmle.label | x | +| view2.rb:7:9:7:10 | [post] self [@x] | semmle.label | [post] self [@x] | +| view2.rb:7:14:7:14 | x | semmle.label | x | +| view3.html.erb:3:1:4:1 | self in view3.html.erb [@x] | semmle.label | self in view3.html.erb [@x] | +| view3.html.erb:3:6:3:8 | call to get | semmle.label | call to get | +| view3.html.erb:3:6:3:8 | self [@x] | semmle.label | self [@x] | +| view3.rb:2:20:2:20 | x | semmle.label | x | +| view3.rb:3:9:3:10 | [post] self [@x] | semmle.label | [post] self [@x] | +| view3.rb:3:14:3:14 | x | semmle.label | x | +| view3.rb:6:5:8:7 | self in get [@x] | semmle.label | self in get [@x] | +| view3.rb:7:9:7:10 | @x | semmle.label | @x | +| view3.rb:7:9:7:10 | self [@x] | semmle.label | self [@x] | +subpaths +| main.rb:4:26:4:26 | x | view1.rb:5:20:5:20 | x | view1.rb:6:9:6:10 | [post] self [@x] | main.rb:4:16:4:27 | call to new [@x] | +| main.rb:16:26:16:26 | x | view3.rb:2:20:2:20 | x | view3.rb:3:9:3:10 | [post] self [@x] | main.rb:16:16:16:27 | call to new [@x] | +| view1.html.erb:6:5:6:13 | call to source | view1.rb:13:13:13:13 | x | view1.rb:14:9:14:10 | [post] self [@x] | view1.html.erb:6:1:6:14 | [post] self [@x] | +| view2.html.erb:3:5:3:13 | call to source | view2.rb:6:13:6:13 | x | view2.rb:7:9:7:10 | [post] self [@x] | view2.html.erb:3:1:3:14 | [post] self [@x] | +| view3.html.erb:3:6:3:8 | self [@x] | view3.rb:6:5:8:7 | self in get [@x] | view3.rb:7:9:7:10 | @x | view3.html.erb:3:6:3:8 | call to get | +#select +| view1.rb:10:14:10:15 | @x | main.rb:3:13:3:21 | call to source | view1.rb:10:14:10:15 | @x | $@ | main.rb:3:13:3:21 | call to source | call to source | +| view1.rb:10:14:10:15 | @x | view1.html.erb:6:5:6:13 | call to source | view1.rb:10:14:10:15 | @x | $@ | view1.html.erb:6:5:6:13 | call to source | call to source | +| view2.rb:3:14:3:15 | @x | view2.html.erb:3:5:3:13 | call to source | view2.rb:3:14:3:15 | @x | $@ | view2.html.erb:3:5:3:13 | call to source | call to source | +| view3.html.erb:3:6:3:8 | call to get | main.rb:15:13:15:21 | call to source | view3.html.erb:3:6:3:8 | call to get | $@ | main.rb:15:13:15:21 | call to source | call to source | diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.ql b/ruby/ql/test/library-tests/dataflow/erb/erb.ql index 18d1664362b6..a3d91150945b 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/erb.ql +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.ql @@ -1,56 +1,13 @@ +/** + * @kind path-problem + */ + import codeql.ruby.AST import codeql.ruby.CFG -import ruby -import codeql.ruby.DataFlow -import codeql.ruby.AST -import codeql.ruby.TaintTracking -import codeql.ruby.frameworks.data.internal.ApiGraphModels -import codeql.ruby.ApiGraphs -import codeql.ruby.dataflow.RemoteFlowSources -private import codeql.ruby.CFG -private import codeql.ruby.dataflow.BarrierGuards -import codeql.ruby.ast.internal.Module -import codeql.ruby.dataflow.internal.DataFlowPrivate -import codeql.ruby.dataflow.SSA - -from ErbFlow::PartialPathNode source, ErbFlow::PartialPathNode sink -where ErbFlow::partialFlow(source, sink, _) -select source, sink - -module ErbFlow = TaintTracking::Global::FlowExplorationFwd; - -module Erb implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node node) { node.(DataFlow::CallNode).getMethodName() = "source" } - - predicate isSink(DataFlow::Node node) { - node = any(DataFlow::CallNode c | c.getMethodName() = "sink").getArgument(_) - } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isFlowFromViewSelfToTemplate(node1, node2) - } -} - -int explorationLimit() { result = 10 } - -predicate isFlowFromViewSelfToTemplate(DataFlow::Node node1, SsaSelfDefinitionNode node2) { - exists(DataFlow::CallNode call, DataFlow::ClassNode view | - call.getMethodName() = "render" and - call.getArgument(0) = node1 and - view.trackInstance().getAValueReachableFromSource() = node1 and - exists(ErbFile template | - view = getTemplateAssociatedViewClass(template) and node2.getLocation().getFile() = template - ) and - node2.getSelfScope() instanceof Toplevel and - node2.getDefinitionExt() instanceof Ssa::SelfDefinition - ) -} +import TestUtilities.InlineFlowTest +import ValueFlowTest +import ValueFlow::PathGraph -DataFlow::ClassNode getTemplateAssociatedViewClass(ErbFile template) { - // template is in same directory as view - exists(File viewFile | viewFile = result.getADeclaration().getFile() | - template.getParentContainer().getAbsolutePath() = - viewFile.getParentContainer().getAbsolutePath() and - viewFile.getStem() = template.getStem() - ) -} +from ValueFlow::PathNode source, ValueFlow::PathNode sink +where ValueFlow::flowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected b/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected index bc09b81014a3..1b929fb28b75 100644 --- a/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected +++ b/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected @@ -2401,6 +2401,7 @@ | 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 | x | local_dataflow.rb:10:9:10:9 | x | | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | +| local_dataflow.rb:1:1:150:3 | self in local_dataflow.rb | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a | | local_dataflow.rb:2:3:2:3 | b | local_dataflow.rb:3:13:3:13 | b | diff --git a/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected b/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected index 41616fcad906..b76c13f6159e 100644 --- a/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected +++ b/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected @@ -2844,6 +2844,7 @@ | local_dataflow.rb:1:1:7:3 | synthetic splat parameter | local_dataflow.rb:1:9:1:9 | a | | local_dataflow.rb:1:1:150:3 | x | local_dataflow.rb:10:9:10:9 | x | | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | +| local_dataflow.rb:1:1:150:3 | self in local_dataflow.rb | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a | | local_dataflow.rb:2:3:2:3 | b | local_dataflow.rb:3:13:3:13 | b | diff --git a/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected b/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected index 67cc8b4870f9..09e1598caf5a 100644 --- a/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected +++ b/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected @@ -3,25 +3,25 @@ track | params_flow.rb:1:1:3:3 | self in taint | type tracker without call steps | params_flow.rb:1:1:3:3 | self in taint | | params_flow.rb:1:1:3:3 | synthetic splat parameter | type tracker without call steps | params_flow.rb:1:1:3:3 | synthetic splat parameter | | params_flow.rb:1:1:3:3 | taint | type tracker without call steps | params_flow.rb:1:1:3:3 | taint | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:1:1:3:3 | self in taint | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:5:1:7:3 | self in sink | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:9:1:12:3 | self in positional | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:16:1:19:3 | self in keyword | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:25:1:31:3 | self in kwargs | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:49:1:53:3 | self in posargs | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:64:1:66:3 | self in splatstuff | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:69:1:76:3 | self in splatmid | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:83:1:91:3 | self in pos_many | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:98:1:103:3 | self in splatmidsmall | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:108:1:112:3 | self in splat_followed_by_keyword_param | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:120:1:126:3 | self in destruct | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:133:1:135:3 | self in splatall | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:139:1:141:3 | self in hashSplatSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:153:1:155:3 | self in keywordSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:167:1:169:3 | self in splatSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:181:1:183:3 | self in positionSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker with call steps | params_flow.rb:200:1:205:3 | self in foo | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | type tracker without call steps | params_flow.rb:1:1:207:15 | self (params_flow.rb) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:1:1:3:3 | self in taint | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:5:1:7:3 | self in sink | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:9:1:12:3 | self in positional | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:16:1:19:3 | self in keyword | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:25:1:31:3 | self in kwargs | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:49:1:53:3 | self in posargs | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:64:1:66:3 | self in splatstuff | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:69:1:76:3 | self in splatmid | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:83:1:91:3 | self in pos_many | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:98:1:103:3 | self in splatmidsmall | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:108:1:112:3 | self in splat_followed_by_keyword_param | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:120:1:126:3 | self in destruct | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:133:1:135:3 | self in splatall | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:139:1:141:3 | self in hashSplatSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:153:1:155:3 | self in keywordSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:167:1:169:3 | self in splatSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:181:1:183:3 | self in positionSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker with call steps | params_flow.rb:200:1:205:3 | self in foo | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | type tracker without call steps | params_flow.rb:1:1:207:15 | self in params_flow.rb | | params_flow.rb:1:11:1:11 | x | type tracker with call steps | params_flow.rb:5:10:5:10 | x | | params_flow.rb:1:11:1:11 | x | type tracker with call steps | params_flow.rb:9:16:9:17 | p1 | | params_flow.rb:1:11:1:11 | x | type tracker with call steps | params_flow.rb:9:20:9:21 | p2 | @@ -3692,215 +3692,216 @@ trackEnd | params_flow.rb:1:1:3:3 | self in taint | params_flow.rb:1:1:3:3 | self in taint | | params_flow.rb:1:1:3:3 | synthetic splat parameter | params_flow.rb:1:1:3:3 | synthetic splat parameter | | params_flow.rb:1:1:3:3 | taint | params_flow.rb:1:1:3:3 | taint | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:1:1:3:3 | self in taint | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:1:1:207:15 | self (params_flow.rb) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:5:1:7:3 | self (sink) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:5:1:7:3 | self in sink | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:6:5:6:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:9:1:12:3 | self (positional) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:9:1:12:3 | self in positional | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:10:5:10:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:11:5:11:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:14:1:14:30 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:14:12:14:19 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:14:22:14:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:16:1:19:3 | self (keyword) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:16:1:19:3 | self in keyword | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:17:5:17:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:18:5:18:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:21:1:21:35 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:21:13:21:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:21:27:21:34 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:22:1:22:35 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:22:13:22:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:22:27:22:34 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:23:1:23:41 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:23:16:23:23 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:23:33:23:40 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:25:1:31:3 | self (kwargs) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:25:1:31:3 | self in kwargs | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:26:5:26:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:27:5:27:22 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:28:5:28:22 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:29:5:29:22 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:30:5:30:22 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:33:1:33:58 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:33:12:33:19 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:33:26:33:34 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:33:41:33:49 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:34:14:34:22 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:35:1:35:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:35:12:35:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:37:16:37:24 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:37:34:37:42 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:38:1:38:14 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:40:16:40:24 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:41:1:41:30 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:41:13:41:21 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:43:9:43:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:44:1:44:28 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:44:12:44:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:46:9:46:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:46:20:46:28 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:47:1:47:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:49:1:53:3 | self (posargs) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:49:1:53:3 | self in posargs | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:50:5:50:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:51:5:51:21 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:52:5:52:21 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:55:1:55:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:55:9:55:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:55:20:55:28 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:57:9:57:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:58:1:58:25 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:58:9:58:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:60:9:60:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:60:20:60:28 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:61:1:61:14 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:63:8:63:16 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:64:1:66:3 | self (splatstuff) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:64:1:66:3 | self in splatstuff | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:65:5:65:13 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:67:1:67:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:69:1:76:3 | self (splatmid) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:69:1:76:3 | self in splatmid | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:70:5:70:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:71:5:71:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:72:5:72:13 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:73:5:73:13 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:74:5:74:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:75:5:75:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:78:1:78:63 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:78:10:78:18 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:78:21:78:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:78:32:78:40 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:78:43:78:51 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:78:54:78:62 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:80:9:80:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:80:20:80:28 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:80:31:80:39 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:80:42:80:50 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:81:1:81:37 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:81:10:81:18 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:81:28:81:36 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:83:1:91:3 | self (pos_many) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:83:1:91:3 | self in pos_many | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:84:5:84:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:85:5:85:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:86:5:86:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:87:5:87:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:88:5:88:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:89:5:89:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:90:5:90:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:93:9:93:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:93:20:93:28 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:93:31:93:39 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:93:42:93:50 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:94:1:94:48 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:94:10:94:18 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:94:21:94:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:94:39:94:47 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:1:96:88 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:10:96:18 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:21:96:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:34:96:42 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:45:96:53 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:56:96:64 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:68:96:76 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:96:79:96:87 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:98:1:103:3 | self (splatmidsmall) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:98:1:103:3 | self in splatmidsmall | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:99:5:99:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:100:5:100:18 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:101:5:101:18 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:102:5:102:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:105:1:105:49 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:105:15:105:23 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:105:28:105:36 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:105:39:105:47 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:106:1:106:46 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:106:15:106:23 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:106:26:106:34 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:106:37:106:45 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:108:1:112:3 | self (splat_followed_by_keyword_param) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:108:1:112:3 | self in splat_followed_by_keyword_param | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:109:5:109:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:110:5:110:13 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:111:5:111:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:114:1:114:67 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:114:33:114:41 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:114:44:114:52 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:114:58:114:66 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:117:3:117:14 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:117:19:117:27 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:118:1:118:14 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:120:1:126:3 | self (destruct) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:120:1:126:3 | self in destruct | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:121:5:121:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:122:5:122:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:123:5:123:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:124:5:124:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:125:5:125:10 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:128:1:128:61 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:128:11:128:19 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:128:22:128:30 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:128:35:128:43 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:128:50:128:58 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:130:9:130:17 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:130:20:130:28 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:131:1:131:46 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:131:17:131:25 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:133:1:135:3 | self (splatall) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:133:1:135:3 | self in splatall | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:134:5:134:16 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:137:1:137:44 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:137:12:137:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:137:23:137:31 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:137:34:137:42 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:139:1:141:3 | self in hashSplatSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:143:24:143:32 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:144:1:144:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:145:1:145:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:146:1:146:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:149:1:149:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:150:1:150:42 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:150:33:150:41 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:151:1:151:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:153:1:155:3 | self in keywordSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:157:24:157:32 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:158:1:158:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:159:1:159:27 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:160:1:160:20 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:163:1:163:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:164:1:164:40 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:164:31:164:39 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:165:1:165:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:167:1:169:3 | self in splatSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:171:17:171:25 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:172:1:172:19 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:173:1:173:25 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:174:1:174:19 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:177:1:177:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:178:1:178:30 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:178:21:178:29 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:179:1:179:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:181:1:183:3 | self in positionSideEffect | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:185:14:185:22 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:186:1:186:16 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:187:1:187:25 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:188:1:188:16 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:191:1:191:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:192:1:192:33 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:192:24:192:32 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:193:1:193:11 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:196:10:196:18 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:200:1:205:3 | self (foo) | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:200:1:205:3 | self in foo | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:201:5:201:15 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:202:5:202:15 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:203:5:203:15 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:204:5:204:15 | self | -| params_flow.rb:1:1:207:15 | self (params_flow.rb) | params_flow.rb:207:1:207:14 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:1:1:3:3 | self in taint | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:1:1:207:15 | self (params_flow.rb) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:1:1:207:15 | self in params_flow.rb | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:5:1:7:3 | self (sink) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:5:1:7:3 | self in sink | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:6:5:6:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:9:1:12:3 | self (positional) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:9:1:12:3 | self in positional | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:10:5:10:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:11:5:11:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:14:1:14:30 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:14:12:14:19 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:14:22:14:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:16:1:19:3 | self (keyword) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:16:1:19:3 | self in keyword | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:17:5:17:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:18:5:18:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:21:1:21:35 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:21:13:21:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:21:27:21:34 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:22:1:22:35 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:22:13:22:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:22:27:22:34 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:23:1:23:41 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:23:16:23:23 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:23:33:23:40 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:25:1:31:3 | self (kwargs) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:25:1:31:3 | self in kwargs | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:26:5:26:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:27:5:27:22 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:28:5:28:22 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:29:5:29:22 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:30:5:30:22 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:33:1:33:58 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:33:12:33:19 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:33:26:33:34 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:33:41:33:49 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:34:14:34:22 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:35:1:35:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:35:12:35:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:37:16:37:24 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:37:34:37:42 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:38:1:38:14 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:40:16:40:24 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:41:1:41:30 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:41:13:41:21 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:43:9:43:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:44:1:44:28 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:44:12:44:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:46:9:46:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:46:20:46:28 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:47:1:47:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:49:1:53:3 | self (posargs) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:49:1:53:3 | self in posargs | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:50:5:50:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:51:5:51:21 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:52:5:52:21 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:55:1:55:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:55:9:55:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:55:20:55:28 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:57:9:57:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:58:1:58:25 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:58:9:58:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:60:9:60:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:60:20:60:28 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:61:1:61:14 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:63:8:63:16 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:64:1:66:3 | self (splatstuff) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:64:1:66:3 | self in splatstuff | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:65:5:65:13 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:67:1:67:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:69:1:76:3 | self (splatmid) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:69:1:76:3 | self in splatmid | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:70:5:70:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:71:5:71:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:72:5:72:13 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:73:5:73:13 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:74:5:74:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:75:5:75:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:78:1:78:63 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:78:10:78:18 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:78:21:78:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:78:32:78:40 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:78:43:78:51 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:78:54:78:62 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:80:9:80:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:80:20:80:28 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:80:31:80:39 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:80:42:80:50 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:81:1:81:37 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:81:10:81:18 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:81:28:81:36 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:83:1:91:3 | self (pos_many) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:83:1:91:3 | self in pos_many | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:84:5:84:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:85:5:85:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:86:5:86:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:87:5:87:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:88:5:88:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:89:5:89:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:90:5:90:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:93:9:93:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:93:20:93:28 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:93:31:93:39 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:93:42:93:50 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:94:1:94:48 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:94:10:94:18 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:94:21:94:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:94:39:94:47 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:1:96:88 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:10:96:18 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:21:96:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:34:96:42 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:45:96:53 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:56:96:64 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:68:96:76 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:96:79:96:87 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:98:1:103:3 | self (splatmidsmall) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:98:1:103:3 | self in splatmidsmall | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:99:5:99:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:100:5:100:18 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:101:5:101:18 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:102:5:102:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:105:1:105:49 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:105:15:105:23 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:105:28:105:36 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:105:39:105:47 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:106:1:106:46 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:106:15:106:23 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:106:26:106:34 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:106:37:106:45 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:108:1:112:3 | self (splat_followed_by_keyword_param) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:108:1:112:3 | self in splat_followed_by_keyword_param | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:109:5:109:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:110:5:110:13 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:111:5:111:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:114:1:114:67 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:114:33:114:41 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:114:44:114:52 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:114:58:114:66 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:117:3:117:14 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:117:19:117:27 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:118:1:118:14 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:120:1:126:3 | self (destruct) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:120:1:126:3 | self in destruct | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:121:5:121:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:122:5:122:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:123:5:123:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:124:5:124:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:125:5:125:10 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:128:1:128:61 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:128:11:128:19 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:128:22:128:30 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:128:35:128:43 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:128:50:128:58 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:130:9:130:17 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:130:20:130:28 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:131:1:131:46 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:131:17:131:25 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:133:1:135:3 | self (splatall) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:133:1:135:3 | self in splatall | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:134:5:134:16 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:137:1:137:44 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:137:12:137:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:137:23:137:31 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:137:34:137:42 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:139:1:141:3 | self in hashSplatSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:143:24:143:32 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:144:1:144:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:145:1:145:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:146:1:146:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:149:1:149:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:150:1:150:42 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:150:33:150:41 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:151:1:151:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:153:1:155:3 | self in keywordSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:157:24:157:32 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:158:1:158:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:159:1:159:27 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:160:1:160:20 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:163:1:163:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:164:1:164:40 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:164:31:164:39 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:165:1:165:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:167:1:169:3 | self in splatSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:171:17:171:25 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:172:1:172:19 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:173:1:173:25 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:174:1:174:19 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:177:1:177:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:178:1:178:30 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:178:21:178:29 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:179:1:179:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:181:1:183:3 | self in positionSideEffect | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:185:14:185:22 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:186:1:186:16 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:187:1:187:25 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:188:1:188:16 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:191:1:191:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:192:1:192:33 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:192:24:192:32 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:193:1:193:11 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:196:10:196:18 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:200:1:205:3 | self (foo) | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:200:1:205:3 | self in foo | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:201:5:201:15 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:202:5:202:15 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:203:5:203:15 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:204:5:204:15 | self | +| params_flow.rb:1:1:207:15 | self in params_flow.rb | params_flow.rb:207:1:207:14 | self | | params_flow.rb:1:11:1:11 | x | params_flow.rb:1:11:1:11 | x | | params_flow.rb:1:11:1:11 | x | params_flow.rb:1:11:1:11 | x | | params_flow.rb:1:11:1:11 | x | params_flow.rb:1:11:1:11 | x | diff --git a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected index 31af9cc7a701..d843d8e3c6d2 100644 --- a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected +++ b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected @@ -1,8 +1,8 @@ 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 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 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:1:1:53:4 | self in 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 in 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 in type_tracker.rb | type tracker without call steps | type_tracker.rb:1:1:53:4 | self in 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 | self in field= | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field | @@ -346,19 +346,20 @@ track | type_tracker.rb:52:5:52:13 | synthetic splat argument | type tracker without call steps | type_tracker.rb:52:5:52:13 | synthetic splat argument | trackEnd | type_tracker.rb:1:1:10:3 | self (Container) | type_tracker.rb:1:1:10:3 | self (Container) | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:18:1:21:3 | self (positional) | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:18:1:21:3 | self in positional | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:19:5:19:11 | self | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:20:5:20:11 | self | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:23:1:23:16 | self | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:25:1:28:3 | self (keyword) | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:25:1:28:3 | self in keyword | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:26:5:26:11 | self | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:27:5:27:11 | self | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:30:1:30:21 | self | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:31:1:31:21 | self | -| type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | type_tracker.rb:32:1:32:27 | self | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:1:1:53:4 | self (type_tracker.rb) | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:1:1:53:4 | self in type_tracker.rb | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:18:1:21:3 | self (positional) | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:18:1:21:3 | self in positional | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:19:5:19:11 | self | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:20:5:20:11 | self | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:23:1:23:16 | self | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:25:1:28:3 | self (keyword) | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:25:1:28:3 | self in keyword | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:26:5:26:11 | self | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:27:5:27:11 | self | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:30:1:30:21 | self | +| type_tracker.rb:1:1:53:4 | self in type_tracker.rb | type_tracker.rb:31:1:31:21 | self | +| type_tracker.rb:1:1:53:4 | self in 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 | self in field= | type_tracker.rb:2:5:5:7 | self (field=) | From 619fb9e55927df4248f96e9b53045e4521e495f4 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 22 Jan 2024 10:09:39 +0100 Subject: [PATCH 7/9] Add change note --- ruby/ql/lib/change-notes/2024-01-22-erb-render-flow.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ruby/ql/lib/change-notes/2024-01-22-erb-render-flow.md diff --git a/ruby/ql/lib/change-notes/2024-01-22-erb-render-flow.md b/ruby/ql/lib/change-notes/2024-01-22-erb-render-flow.md new file mode 100644 index 000000000000..f9e68ef580e9 --- /dev/null +++ b/ruby/ql/lib/change-notes/2024-01-22-erb-render-flow.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Flow is now tracked through Rails `render` calls, when the argument is a `ViewComponent`. In this case, data flow is tracked into the accompanying `.html.erb` file. From d1fa338e4ba624fbcf43f0cfa7627b713a6081ec Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 13 Dec 2023 09:44:50 +0100 Subject: [PATCH 8/9] Ruby: Track types in data flow --- .../DataFlowConsistency.ql | 8 + .../dataflow/internal/DataFlowDispatch.qll | 173 +------- .../dataflow/internal/DataFlowPrivate.qll | 374 +++++++++++++++++- .../ruby/dataflow/internal/DataFlowPublic.qll | 19 + .../internal/TaintTrackingPrivate.qll | 9 +- .../ql/lib/codeql/ruby/frameworks/Sinatra.qll | 18 +- .../library-tests/dataflow/erb/erb.expected | 116 +++--- .../test/library-tests/dataflow/erb/main.rb | 3 + .../test/library-tests/dataflow/erb/view1.rb | 3 - .../dataflow/global/Flow.expected | 263 ++++++------ .../dataflow/type-flow/Flow.expected | 371 +++++++++++++++++ .../library-tests/dataflow/type-flow/Flow.ql | 54 +++ .../library-tests/dataflow/type-flow/types.rb | 89 +++++ .../action_controller/params-flow.expected | 92 +++-- .../frameworks/pathname/Pathname.expected | 2 - .../frameworks/sinatra/Sinatra.expected | 64 ++- .../TemplateInjection.expected | 6 +- .../security/cwe-022/PathInjection.expected | 6 +- .../security/cwe-089/SqlInjection.expected | 57 ++- .../CodeInjection/CodeInjection.expected | 36 +- .../cwe-312/CleartextLogging.expected | 156 ++++---- .../cwe-312/CleartextStorage.expected | 132 ++++--- .../HardcodedDataInterpretedAsCode.expected | 50 +-- .../cwe-732/WeakFilePermissions.expected | 32 +- .../cwe-798/HardcodedCredentials.expected | 64 +-- .../cwe-829/InsecureDownload.expected | 22 +- .../internal/DataFlowImplConsistency.qll | 4 + 27 files changed, 1488 insertions(+), 735 deletions(-) create mode 100644 ruby/ql/test/library-tests/dataflow/type-flow/Flow.expected create mode 100644 ruby/ql/test/library-tests/dataflow/type-flow/Flow.ql create mode 100644 ruby/ql/test/library-tests/dataflow/type-flow/types.rb diff --git a/ruby/ql/consistency-queries/DataFlowConsistency.ql b/ruby/ql/consistency-queries/DataFlowConsistency.ql index d064eeb3701d..0da347b36223 100644 --- a/ruby/ql/consistency-queries/DataFlowConsistency.ql +++ b/ruby/ql/consistency-queries/DataFlowConsistency.ql @@ -44,6 +44,14 @@ private module Input implements InputSig { n.getASplit() instanceof Split::ConditionalCompletionSplit ) } + + predicate uniqueTypeExclude(Node n) { + n = + any(DataFlow::CallNode call | + Private::isStandardNewCall(call.getExprNode(), _, _) and + not call.getReceiver().asExpr().getExpr() instanceof ConstantReadAccess + ) + } } import MakeConsistency diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll index 2e491e4fba71..db3431fb846a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll @@ -237,7 +237,7 @@ class NormalCall extends DataFlowCall, TNormalCall { * need to track the `View` instance (2) into the receiver of the adjusted method * call, in order to figure out that the call target is in fact `view.html.erb`. */ -private module ViewComponentRenderModeling { +module ViewComponentRenderModeling { private import codeql.ruby.frameworks.ViewComponent private class RenderMethod extends SummarizedCallable, LibraryCallableToIncludeInTypeTracking { @@ -333,7 +333,7 @@ private predicate selfInModule(SelfVariable self, Module m) { /** Holds if `self` belongs to method `method` inside module `m`. */ pragma[nomagic] -private predicate selfInMethod(SelfVariable self, MethodBase method, Module m) { +predicate selfInMethod(SelfVariable self, MethodBase method, Module m) { exists(ModuleBase encl | method = self.getDeclaringScope() and encl = method.getEnclosingModule() and @@ -343,67 +343,6 @@ private predicate selfInMethod(SelfVariable self, MethodBase method, Module m) { ) } -/** Holds if `self` belongs to the top-level. */ -pragma[nomagic] -private predicate selfInToplevel(SelfVariable self, Module m) { - ViewComponentRenderModeling::selfInErbToplevel(self, m) - or - not ViewComponentRenderModeling::selfInErbToplevel(self, _) and - self.getDeclaringScope() instanceof Toplevel and - m = Module::TResolved("Object") -} - -/** - * Holds if SSA definition `def` belongs to a variable introduced via pattern - * matching on type `m`. For example, in - * - * ```rb - * case object - * in C => c then c.foo - * end - * ``` - * - * the SSA definition for `c` is introduced by matching on `C`. - */ -private predicate asModulePattern(SsaDefinitionExtNode def, Module m) { - exists(AsPattern ap | - m = Module::resolveConstantReadAccess(ap.getPattern()) and - def.getDefinitionExt().(Ssa::WriteDefinition).getWriteAccess().getAstNode() = - ap.getVariableAccess() - ) -} - -/** - * Holds if `read1` and `read2` are adjacent reads of SSA definition `def`, - * and `read2` is checked to have type `m`. For example, in - * - * ```rb - * case object - * when C then object.foo - * end - * ``` - * - * the two reads of `object` are adjacent, and the second is checked to have type `C`. - */ -private predicate hasAdjacentTypeCheckedReads( - Ssa::Definition def, CfgNodes::ExprCfgNode read1, CfgNodes::ExprCfgNode read2, Module m -) { - exists( - CfgNodes::ExprCfgNode pattern, ConditionBlock cb, CfgNodes::ExprNodes::CaseExprCfgNode case - | - m = Module::resolveConstantReadAccess(pattern.getExpr()) and - cb.getLastNode() = pattern and - cb.controls(read2.getBasicBlock(), - any(SuccessorTypes::MatchingSuccessor match | match.getValue() = true)) and - def.hasAdjacentReads(read1, read2) and - case.getValue() = read1 - | - pattern = case.getBranch(_).(CfgNodes::ExprNodes::WhenClauseCfgNode).getPattern(_) - or - pattern = case.getBranch(_).(CfgNodes::ExprNodes::InClauseCfgNode).getPattern() - ) -} - /** Holds if `new` is a user-defined `self.new` method. */ predicate isUserDefinedNew(SingletonMethod new) { exists(Expr object | singletonMethod(new, "new", object) | @@ -617,7 +556,7 @@ private predicate hasUserDefinedNew(Module m) { * `self.new` on `m`. */ pragma[nomagic] -private predicate isStandardNewCall(RelevantCall new, Module m, boolean exact) { +predicate isStandardNewCall(RelevantCall new, Module m, boolean exact) { exists(DataFlow::LocalSourceNode sourceNode | flowsToMethodCallReceiver(TNormalCall(new), sourceNode, "new") and // `m` should not have a user-defined `self.new` method @@ -646,106 +585,11 @@ private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, } private module TrackInstanceInput implements CallGraphConstruction::InputSig { - pragma[nomagic] - private predicate isInstanceNoCall(DataFlow::Node n, Module tp, boolean exact) { - n.asExpr().getExpr() instanceof NilLiteral and - tp = Module::TResolved("NilClass") and - exact = true - or - n.asExpr().getExpr().(BooleanLiteral).isFalse() and - tp = Module::TResolved("FalseClass") and - exact = true - or - n.asExpr().getExpr().(BooleanLiteral).isTrue() and - tp = Module::TResolved("TrueClass") and - exact = true - or - n.asExpr().getExpr() instanceof IntegerLiteral and - tp = Module::TResolved("Integer") and - exact = true - or - n.asExpr().getExpr() instanceof FloatLiteral and - tp = Module::TResolved("Float") and - exact = true - or - n.asExpr().getExpr() instanceof RationalLiteral and - tp = Module::TResolved("Rational") and - exact = true - or - n.asExpr().getExpr() instanceof ComplexLiteral and - tp = Module::TResolved("Complex") and - exact = true - or - n.asExpr().getExpr() instanceof StringlikeLiteral and - tp = Module::TResolved("String") and - exact = true - or - n.asExpr() instanceof CfgNodes::ExprNodes::ArrayLiteralCfgNode and - tp = Module::TResolved("Array") and - exact = true - or - n.asExpr() instanceof CfgNodes::ExprNodes::HashLiteralCfgNode and - tp = Module::TResolved("Hash") and - exact = true - or - n.asExpr().getExpr() instanceof MethodBase and - tp = Module::TResolved("Symbol") and - exact = true - or - n.asParameter() instanceof BlockParameter and - tp = Module::TResolved("Proc") and - exact = true - or - n.asExpr().getExpr() instanceof Lambda and - tp = Module::TResolved("Proc") and - exact = true - or - // `self` reference in method or top-level (but not in module or singleton method, - // where instance methods cannot be called; only singleton methods) - n = - any(SelfLocalSourceNode self | - exists(MethodBase m | - selfInMethod(self.getVariable(), m, tp) and - not m instanceof SingletonMethod and - if m.getEnclosingModule() instanceof Toplevel then exact = true else exact = false - ) - or - selfInToplevel(self.getVariable(), tp) and - exact = true - ) - or - // `in C => c then c.foo` - asModulePattern(n, tp) and - exact = false - or - // `case object when C then object.foo` - hasAdjacentTypeCheckedReads(_, _, n.asExpr(), tp) and - exact = false - } - - pragma[nomagic] - private predicate isInstanceCall(DataFlow::Node n, Module tp, boolean exact) { - isStandardNewCall(n.asExpr(), tp, exact) - } - - /** Holds if `n` is an instance of type `tp`. */ - pragma[inline] - private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) { - isInstanceNoCall(n, tp, exact) - or - isInstanceCall(n, tp, exact) - } - - pragma[nomagic] - private predicate hasAdjacentTypeCheckedReads(DataFlow::Node node) { - hasAdjacentTypeCheckedReads(_, _, node.asExpr(), _) - } - newtype State = additional MkState(Module m, Boolean exact) predicate start(DataFlow::Node start, State state) { exists(Module tp, boolean exact | state = MkState(tp, exact) | - isInstance(start, tp, exact) + TypeInference::hasType(start, tp, exact) or exists(Module m | (if m.isClass() then tp = Module::TResolved("Class") else tp = Module::TResolved("Module")) and @@ -763,6 +607,11 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig { ) } + pragma[nomagic] + private predicate hasAdjacentTypeCheckedRead(DataFlow::Node node) { + TypeInference::hasAdjacentTypeCheckedRead(node.asExpr(), _) + } + pragma[nomagic] predicate stepNoCall(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, StepSummary summary) { smallStepNoCall(nodeFrom, nodeTo, summary) @@ -770,8 +619,8 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig { // We exclude steps into type checked variables. For those, we instead rely on the // type being checked against localFlowStep(nodeFrom, nodeTo, summary) and - not hasAdjacentTypeCheckedReads(nodeTo) and - not asModulePattern(nodeTo, _) + not hasAdjacentTypeCheckedRead(nodeTo) and + not TypeInference::asModulePattern(nodeTo.(SsaDefinitionExtNode).getDefinitionExt(), _) } predicate stepCall(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, StepSummary summary) { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index ebe9b1a1b392..ed90e13fec3d 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -769,6 +769,7 @@ private module Cached { cached newtype TDataFlowType = + TModuleDataFlowType(Module m) or TLambdaDataFlowType(Callable c) { c = any(LambdaSelfReferenceNode n).getCallable() } or // In order to reduce the set of cons-candidates, we annotate all implicit (hash) splat // creations with the name of the method that they are passed into. This includes @@ -780,6 +781,7 @@ private module Cached { TSynthSplatArgumentType(string methodName) { methodName = any(SynthSplatArgumentNode n).getMethodName() } or + TCollectionType() or TUnknownDataFlowType() } @@ -1047,6 +1049,8 @@ private module ParameterNodes { final Callable getCallable() { result = callable } + Node getALocalSuccessor() { VariableCapture::valueStep(this, result) } + override Parameter getParameter() { none() } override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { @@ -1939,21 +1943,91 @@ predicate expectsContent(Node n, ContentSet c) { } class DataFlowType extends TDataFlowType { - string toString() { result = "" } + string toString() { + exists(Module m | + this = TModuleDataFlowType(m) and + result = m.toString() + ) + or + exists(Callable c | this = TLambdaDataFlowType(c) | result = "[lambda] " + c.toString()) + or + exists(string methodName | this = TSynthHashSplatArgumentType(methodName) | + result = "[hash-splat] " + methodName + ) + or + exists(string methodName | this = TSynthSplatArgumentType(methodName) | + result = "[splat] " + methodName + ) + or + this = TCollectionType() and result = "[collection]" + or + this = TUnknownDataFlowType() and + result = "[unknown]" + } + + predicate isUnknown() { this = TUnknownDataFlowType() } + + Location getLocation() { + exists(Module m | + this = TModuleDataFlowType(m) and + result = m.getLocation() + ) + or + exists(Callable c | this = TLambdaDataFlowType(c) and result = c.getLocation()) + } +} + +pragma[nomagic] +private predicate isProcClass(DataFlowType t) { + t = TModuleDataFlowType(any(TypeInference::ProcClass m)) } +pragma[nomagic] +private predicate isArrayClass(DataFlowType t) { + t = TModuleDataFlowType(any(TypeInference::ArrayClass m).getADescendent()) +} + +pragma[nomagic] +private predicate isHashClass(DataFlowType t) { + t = TModuleDataFlowType(any(TypeInference::HashClass m).getADescendent()) +} + +private predicate isCollectionClass(DataFlowType t) { isArrayClass(t) or isHashClass(t) } + predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { - t1 != TUnknownDataFlowType() and - t2 = TUnknownDataFlowType() + not t1.isUnknown() and + t2.isUnknown() + or + exists(Module m1, Module m2 | + t1 = TModuleDataFlowType(m1) and + t2 = TModuleDataFlowType(m2) and + m1.getAnImmediateAncestor+() = m2 + ) + or + t1 instanceof TLambdaDataFlowType and + isProcClass(t2) } -private predicate mustHaveLambdaType(ExprNode n, Callable c) { +private predicate mustHaveLambdaType(Node n, Callable c) { exists(VariableCapture::ClosureExpr ce, CfgNodes::ExprCfgNode e | e = n.asExpr() and ce.hasBody(c) | e = ce or ce.hasAliasedAccess(e) ) + or + n.(CaptureNode).getSynthesizedCaptureNode().isInstanceAccess() and + c = n.(CaptureNode).getSynthesizedCaptureNode().getEnclosingCallable() +} + +private predicate mustHaveCollectionType(Node n, DataFlowType t) { + exists(ContentSet c | readStep(n, c, _) or storeStep(_, c, n) or expectsContent(n, c) | + c.isElement() and + t = TCollectionType() + ) and + not n instanceof SynthHashSplatOrSplatArgumentNode and + not n instanceof SynthHashSplatParameterNode and + not n instanceof SynthSplatParameterNode } predicate localMustFlowStep(Node node1, Node node2) { none() } @@ -1971,19 +2045,53 @@ DataFlowType getNodeType(Node n) { or result = TSynthSplatArgumentType(n.(SynthSplatArgumentNode).getMethodName()) or + mustHaveCollectionType(n, result) + or not n instanceof LambdaSelfReferenceNode and not mustHaveLambdaType(n, _) and + not mustHaveCollectionType(n, _) and not n instanceof SynthHashSplatOrSplatArgumentNode and - result = TUnknownDataFlowType() + ( + TypeInference::hasModuleType(n, result) + or + not TypeInference::hasModuleType(n, _) and + result.isUnknown() + ) } /** Gets a string representation of a `DataFlowType`. */ -string ppReprType(DataFlowType t) { none() } +string ppReprType(DataFlowType t) { + t instanceof TModuleDataFlowType and + result = t.toString() +} pragma[inline] private predicate compatibleTypesNonSymRefl(DataFlowType t1, DataFlowType t2) { - t1 != TUnknownDataFlowType() and - t2 = TUnknownDataFlowType() + not t1.isUnknown() and + t2.isUnknown() + or + t1 instanceof TLambdaDataFlowType and + isProcClass(t2) + or + t1 instanceof TSynthSplatArgumentType and + (isArrayClass(t2) or t2 instanceof TCollectionType) + or + t1 instanceof TSynthHashSplatArgumentType and + (isHashClass(t2) or t2 instanceof TCollectionType) + or + t1 instanceof TCollectionType and + isCollectionClass(t2) +} + +pragma[nomagic] +private predicate compatibleModuleTypes(TModuleDataFlowType t1, TModuleDataFlowType t2) { + exists(Module m1, Module m2, Module m3 | + t1 = TModuleDataFlowType(m1) and + t2 = TModuleDataFlowType(m2) + | + m3.getAnAncestor() = m1 and + m3.getAnAncestor() = m2 + ) } /** @@ -1997,6 +2105,8 @@ predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { compatibleTypesNonSymRefl(t1, t2) or compatibleTypesNonSymRefl(t2, t1) + or + compatibleModuleTypes(t1, t2) } abstract class PostUpdateNodeImpl extends Node { @@ -2056,7 +2166,11 @@ private import PostUpdateNodes /** A node that performs a type cast. */ class CastNode extends Node { - CastNode() { none() } + CastNode() { + TypeInference::hasAdjacentTypeCheckedRead(this.asExpr(), _) + or + TypeInference::asModulePattern(this.(SsaDefinitionNode).getDefinition(), _) + } } /** @@ -2258,3 +2372,245 @@ class AdditionalJumpStep extends Unit { */ abstract predicate step(Node pred, Node succ); } + +/** Provides logic for assigning types to data flow nodes. */ +module TypeInference { + private import codeql.ruby.ast.internal.Module + private import DataFlowDispatch + + /** The built-in `Proc` class. */ + class ProcClass extends Module { + ProcClass() { this = TResolved("Proc") } + } + + /** The built-in `Array` class. */ + class ArrayClass extends Module { + ArrayClass() { this = TResolved("Array") } + } + + /** The built-in `Hash` class. */ + class HashClass extends Module { + HashClass() { this = TResolved("Hash") } + } + + /** The built-in `String` class. */ + class StringClass extends Module { + StringClass() { this = TResolved("String") } + } + + /** Holds if `self` belongs to the top-level. */ + pragma[nomagic] + private predicate selfInToplevel(SelfVariable self, Module m) { + ViewComponentRenderModeling::selfInErbToplevel(self, m) + or + not ViewComponentRenderModeling::selfInErbToplevel(self, _) and + self.getDeclaringScope() instanceof Toplevel and + m = TResolved("Object") + } + + /** + * Holds if SSA definition `def` belongs to a variable introduced via pattern + * matching on type `m`. For example, in + * + * ```rb + * case object + * in C => c then c.foo + * end + * ``` + * + * the SSA definition for `c` is introduced by matching on `C`. + */ + predicate asModulePattern(Ssa::WriteDefinition def, Module m) { + exists(AsPattern ap | + m = resolveConstantReadAccess(ap.getPattern()) and + def.getWriteAccess().getAstNode() = ap.getVariableAccess() + ) + } + + /** + * Holds if `caseRead` and `read` are reads of SSA definition `def`, + * and `read` is checked to have type `m`. For example, in + * + * ```rb + * case object + * when C then object.foo + * end + * ``` + * + * the second read of `object` is known to have type `C`. + */ + private predicate hasTypeCheckedRead( + Ssa::Definition def, CfgNodes::ExprCfgNode caseRead, CfgNodes::ExprCfgNode read, Module m + ) { + exists( + CfgNodes::ExprCfgNode pattern, ConditionBlock cb, CfgNodes::ExprNodes::CaseExprCfgNode case + | + m = resolveConstantReadAccess(pattern.getExpr()) and + cb.getLastNode() = pattern and + cb.controls(read.getBasicBlock(), + any(SuccessorTypes::MatchingSuccessor match | match.getValue() = true)) and + caseRead = def.getARead() and + read = def.getARead() and + case.getValue() = caseRead + | + pattern = case.getBranch(_).(CfgNodes::ExprNodes::WhenClauseCfgNode).getPattern(_) + or + pattern = case.getBranch(_).(CfgNodes::ExprNodes::InClauseCfgNode).getPattern() + ) + } + + predicate hasAdjacentTypeCheckedRead(CfgNodes::ExprCfgNode read, Module m) { + exists(Ssa::Definition def, CfgNodes::ExprCfgNode caseRead | + hasTypeCheckedRead(def, caseRead, read, m) and + def.hasAdjacentReads(caseRead, read) + ) + } + + private predicate isTypeCheckedRead(CfgNodes::ExprCfgNode read, Module m) { + exists(Ssa::Definition def | + hasTypeCheckedRead(def, _, read, m) and + // could in principle be checked against a new type + not exists(CfgNodes::ExprCfgNode innerCaseRead | + hasTypeCheckedRead(def, _, innerCaseRead, m) and + hasTypeCheckedRead(def, innerCaseRead, read, _) + ) + ) + } + + pragma[nomagic] + private predicate selfInMethodOrToplevelHasType(SelfVariable self, Module tp, boolean exact) { + exists(MethodBase m | + selfInMethod(self, m, tp) and + not m instanceof SingletonMethod and + if m.getEnclosingModule() instanceof Toplevel then exact = true else exact = false + ) + or + selfInToplevel(self, tp) and + exact = true + } + + pragma[nomagic] + private predicate parameterNodeHasType(ParameterNodeImpl p, Module tp, boolean exact) { + exists(ParameterPosition pos | + p.isParameterOf(_, pos) and + exact = true + | + (pos.isSplat(_) or pos.isSynthSplat()) and + tp instanceof ArrayClass + or + (pos.isHashSplat() or pos.isSynthHashSplat()) and + tp instanceof HashClass + ) + or + selfInMethodOrToplevelHasType(p.(SelfParameterNodeImpl).getSelfVariable(), tp, exact) + } + + pragma[nomagic] + private predicate ssaDefHasType(SsaDefinitionExtNode def, Module tp, boolean exact) { + exists(ParameterNodeImpl p | + parameterNodeHasType(p, tp, exact) and + LocalFlow::localFlowSsaParamInput(p, def) + ) + or + selfInMethodOrToplevelHasType(def.getVariable(), tp, exact) + or + asModulePattern(def.getDefinitionExt(), tp) and + exact = false + } + + pragma[nomagic] + private predicate hasTypeNoCall(Node n, Module tp, boolean exact) { + n.asExpr().getExpr() instanceof NilLiteral and + tp = TResolved("NilClass") and + exact = true + or + n.asExpr().getExpr().(BooleanLiteral).isFalse() and + tp = TResolved("FalseClass") and + exact = true + or + n.asExpr().getExpr().(BooleanLiteral).isTrue() and + tp = TResolved("TrueClass") and + exact = true + or + n.asExpr().getExpr() instanceof IntegerLiteral and + tp = TResolved("Integer") and + exact = true + or + n.asExpr().getExpr() instanceof FloatLiteral and + tp = TResolved("Float") and + exact = true + or + n.asExpr().getExpr() instanceof RationalLiteral and + tp = TResolved("Rational") and + exact = true + or + n.asExpr().getExpr() instanceof ComplexLiteral and + tp = TResolved("Complex") and + exact = true + or + n.asExpr().getExpr() instanceof StringlikeLiteral and + tp instanceof StringClass and + exact = true + or + ( + n.asExpr() instanceof CfgNodes::ExprNodes::ArrayLiteralCfgNode or + n instanceof SynthSplatArgumentNode + ) and + tp instanceof ArrayClass and + exact = true + or + ( + n.asExpr() instanceof CfgNodes::ExprNodes::HashLiteralCfgNode + or + n instanceof SynthHashSplatArgumentNode + ) and + tp instanceof HashClass and + exact = true + or + n.asExpr().getExpr() instanceof MethodBase and + tp = TResolved("Symbol") and + exact = true + or + ( + n.asParameter() instanceof BlockParameter + or + n instanceof BlockParameterNode + or + n.asExpr().getExpr() instanceof Lambda + ) and + tp instanceof ProcClass and + exact = true + or + parameterNodeHasType(n, tp, exact) + or + exists(SsaDefinitionExtNode def | ssaDefHasType(def, tp, exact) | + n = def or + n.asExpr() = + any(CfgNodes::ExprCfgNode read | + read = def.getDefinitionExt().getARead() and + not isTypeCheckedRead(read, _) // could in principle be checked against a new type + ) + ) + or + // `case object when C then object.foo` + isTypeCheckedRead(n.asExpr(), tp) and + exact = false + } + + pragma[nomagic] + private predicate hasTypeCall(Node n, Module tp, boolean exact) { + isStandardNewCall(n.asExpr(), tp, exact) + } + + pragma[inline] + predicate hasType(Node n, Module tp, boolean exact) { + hasTypeNoCall(n, tp, exact) + or + hasTypeCall(n, tp, exact) + } + + pragma[nomagic] + predicate hasModuleType(Node n, DataFlowType t) { + exists(Module tp | t = TModuleDataFlowType(tp) | hasType(n, tp, _)) + } +} diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll index 8d0c565a7376..ed4efabaf647 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll @@ -727,6 +727,25 @@ class ContentSet extends TContentSet { this = TElementContentOfTypeContent(type, true) } + /** + * Holds if this content set represents an element in a collection (array or hash). + */ + predicate isElement() { + this.isSingleton(any(Content::ElementContent c)) + or + this.isAnyElement() + or + this.isKnownOrUnknownElement(any(Content::KnownElementContent c)) + or + this.isElementLowerBound(_) + or + this.isElementLowerBoundOrUnknown(_) + or + this.isElementOfType(_) + or + this.isElementOfTypeOrUnknown(_) + } + /** Gets a textual representation of this content set. */ string toString() { exists(Content c | diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll index 1f2e8188d725..a8157ba55db0 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll @@ -113,12 +113,9 @@ private module Cached { // Although flow through collections is modeled precisely using stores/reads, we still // allow flow out of a _tainted_ collection. This is needed in order to support taint- // tracking configurations where the source is a collection. - exists(DataFlow::ContentSet c | readStep(nodeFrom, c, nodeTo) | - c.isSingleton(any(DataFlow::Content::ElementContent ec)) - or - c.isKnownOrUnknownElement(_) - or - c.isAnyElement() + exists(DataFlow::ContentSet c | + readStep(nodeFrom, c, nodeTo) and + c.isElement() ) } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll b/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll index 8c7162eeec8b..58e7a60bc2d5 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Sinatra.qll @@ -280,7 +280,7 @@ module Sinatra { // the filter applies to all routes not filter.hasPattern() and blockPostUpdate(pred, filter.getBody()) and - blockSelfParameterNode(succ, route.getBody().asExpr().getExpr()) + blockSelfParameterSuccessorNode(succ, route.getBody().asExpr().getExpr()) ) } } @@ -290,8 +290,18 @@ module Sinatra { n.getPreUpdateNode() = b } - /** Holds if `n` is a `self` parameter belonging to block `b`. */ - private predicate blockSelfParameterNode(DataFlowPrivate::LambdaSelfReferenceNode n, Block b) { - n.getCallable() = b + /** + * Holds if `n` is a successor of a `self` parameter belonging to block `b`. + * + * We use a successor instead of the parameter node itself, because the types + * don't match up; in normal variable capture flow, the type of the `self` + * parameter should always match the type of the lambda itself, but that is not + * the case here. + */ + private predicate blockSelfParameterSuccessorNode(DataFlow::Node n, Block b) { + exists(DataFlowPrivate::LambdaSelfReferenceNode p | + p.getCallable() = b and + n = p.getALocalSuccessor() + ) } } diff --git a/ruby/ql/test/library-tests/dataflow/erb/erb.expected b/ruby/ql/test/library-tests/dataflow/erb/erb.expected index 1ca2216a5590..bb69f8d2be29 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/erb.expected +++ b/ruby/ql/test/library-tests/dataflow/erb/erb.expected @@ -2,103 +2,89 @@ testFailures edges | main.rb:3:9:3:9 | x | main.rb:4:26:4:26 | x | | main.rb:3:13:3:21 | call to source | main.rb:3:9:3:9 | x | -| main.rb:4:9:4:12 | view [@x] | main.rb:5:16:5:19 | view [@x] | -| main.rb:4:16:4:27 | call to new [@x] | main.rb:4:9:4:12 | view [@x] | -| main.rb:4:26:4:26 | x | main.rb:4:16:4:27 | call to new [@x] | -| main.rb:4:26:4:26 | x | view1.rb:5:20:5:20 | x | -| main.rb:5:16:5:19 | view [@x] | view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | +| main.rb:4:9:4:12 | view : View1 [@x] | main.rb:5:16:5:19 | view : View1 [@x] | +| main.rb:4:16:4:27 | call to new : View1 [@x] | main.rb:4:9:4:12 | view : View1 [@x] | +| main.rb:4:26:4:26 | x | main.rb:4:16:4:27 | call to new : View1 [@x] | +| main.rb:5:16:5:19 | view : View1 [@x] | view1.html.erb:2:5:8:1 | self in view1.html.erb : View1 [@x] | | main.rb:10:16:10:19 | [post] view [@x] | main.rb:11:9:11:12 | view [@x] | -| main.rb:11:9:11:12 | view [@x] | view2.rb:2:5:4:7 | self in foo [@x] | +| main.rb:11:9:11:12 | view [@x] | view2.rb:2:5:4:7 | self in foo : View2 [@x] | | main.rb:15:9:15:9 | x | main.rb:16:26:16:26 | x | | main.rb:15:13:15:21 | call to source | main.rb:15:9:15:9 | x | -| main.rb:16:9:16:12 | view [@x] | main.rb:17:16:17:19 | view [@x] | -| main.rb:16:16:16:27 | call to new [@x] | main.rb:16:9:16:12 | view [@x] | -| main.rb:16:26:16:26 | x | main.rb:16:16:16:27 | call to new [@x] | -| main.rb:16:26:16:26 | x | view3.rb:2:20:2:20 | x | -| main.rb:17:16:17:19 | view [@x] | view3.html.erb:3:1:4:1 | self in view3.html.erb [@x] | -| view1.html.erb:2:5:2:9 | self [@x] | view1.rb:9:5:11:7 | self in foo [@x] | -| view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | view1.html.erb:2:5:2:9 | self [@x] | -| view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | view1.html.erb:7:1:7:5 | self [@x] | +| main.rb:16:9:16:12 | view : View3 [@x] | main.rb:17:16:17:19 | view : View3 [@x] | +| main.rb:16:16:16:27 | call to new : View3 [@x] | main.rb:16:9:16:12 | view : View3 [@x] | +| main.rb:16:26:16:26 | x | main.rb:16:16:16:27 | call to new : View3 [@x] | +| main.rb:17:16:17:19 | view : View3 [@x] | view3.html.erb:3:1:4:1 | self in view3.html.erb : View3 [@x] | +| view1.html.erb:2:5:2:9 | self : View1 [@x] | view1.rb:6:5:8:7 | self in foo : View1 [@x] | +| view1.html.erb:2:5:8:1 | self in view1.html.erb : View1 [@x] | view1.html.erb:2:5:2:9 | self : View1 [@x] | +| view1.html.erb:2:5:8:1 | self in view1.html.erb : View1 [@x] | view1.html.erb:7:1:7:5 | self : View1 [@x] | | view1.html.erb:6:1:6:14 | [post] self [@x] | view1.html.erb:7:1:7:5 | self [@x] | | view1.html.erb:6:5:6:13 | call to source | view1.html.erb:6:1:6:14 | [post] self [@x] | -| view1.html.erb:6:5:6:13 | call to source | view1.rb:13:13:13:13 | x | -| view1.html.erb:7:1:7:5 | self [@x] | view1.rb:9:5:11:7 | self in foo [@x] | -| view1.html.erb:7:1:7:5 | self [@x] | view1.rb:9:5:11:7 | self in foo [@x] | -| view1.rb:5:20:5:20 | x | view1.rb:6:14:6:14 | x | -| view1.rb:6:14:6:14 | x | view1.rb:6:9:6:10 | [post] self [@x] | -| view1.rb:9:5:11:7 | self in foo [@x] | view1.rb:10:14:10:15 | self [@x] | -| view1.rb:10:14:10:15 | self [@x] | view1.rb:10:14:10:15 | @x | -| view1.rb:13:13:13:13 | x | view1.rb:14:14:14:14 | x | -| view1.rb:14:14:14:14 | x | view1.rb:14:9:14:10 | [post] self [@x] | +| view1.html.erb:6:5:6:13 | call to source | view1.rb:10:13:10:13 | x | +| view1.html.erb:7:1:7:5 | self : View1 [@x] | view1.rb:6:5:8:7 | self in foo : View1 [@x] | +| view1.html.erb:7:1:7:5 | self [@x] | view1.rb:6:5:8:7 | self in foo : View1 [@x] | +| view1.rb:6:5:8:7 | self in foo : View1 [@x] | view1.rb:7:14:7:15 | self : View1 [@x] | +| view1.rb:7:14:7:15 | self : View1 [@x] | view1.rb:7:14:7:15 | @x | +| view1.rb:10:13:10:13 | x | view1.rb:11:14:11:14 | x | +| view1.rb:11:14:11:14 | x | view1.rb:11:9:11:10 | [post] self [@x] | | view2.html.erb:3:1:3:14 | [post] self [@x] | main.rb:10:16:10:19 | [post] view [@x] | | view2.html.erb:3:5:3:13 | call to source | view2.html.erb:3:1:3:14 | [post] self [@x] | | view2.html.erb:3:5:3:13 | call to source | view2.rb:6:13:6:13 | x | -| view2.rb:2:5:4:7 | self in foo [@x] | view2.rb:3:14:3:15 | self [@x] | -| view2.rb:3:14:3:15 | self [@x] | view2.rb:3:14:3:15 | @x | +| view2.rb:2:5:4:7 | self in foo : View2 [@x] | view2.rb:3:14:3:15 | self : View2 [@x] | +| view2.rb:3:14:3:15 | self : View2 [@x] | view2.rb:3:14:3:15 | @x | | view2.rb:6:13:6:13 | x | view2.rb:7:14:7:14 | x | | view2.rb:7:14:7:14 | x | view2.rb:7:9:7:10 | [post] self [@x] | -| view3.html.erb:3:1:4:1 | self in view3.html.erb [@x] | view3.html.erb:3:6:3:8 | self [@x] | -| view3.html.erb:3:6:3:8 | self [@x] | view3.html.erb:3:6:3:8 | call to get | -| view3.html.erb:3:6:3:8 | self [@x] | view3.rb:6:5:8:7 | self in get [@x] | -| view3.rb:2:20:2:20 | x | view3.rb:3:14:3:14 | x | -| view3.rb:3:14:3:14 | x | view3.rb:3:9:3:10 | [post] self [@x] | -| view3.rb:6:5:8:7 | self in get [@x] | view3.rb:7:9:7:10 | self [@x] | -| view3.rb:7:9:7:10 | self [@x] | view3.rb:7:9:7:10 | @x | +| view3.html.erb:3:1:4:1 | self in view3.html.erb : View3 [@x] | view3.html.erb:3:6:3:8 | self : View3 [@x] | +| view3.html.erb:3:6:3:8 | self : View3 [@x] | view3.html.erb:3:6:3:8 | call to get | +| view3.html.erb:3:6:3:8 | self : View3 [@x] | view3.rb:6:5:8:7 | self in get : View3 [@x] | +| view3.rb:6:5:8:7 | self in get : View3 [@x] | view3.rb:7:9:7:10 | self : View3 [@x] | +| view3.rb:7:9:7:10 | self : View3 [@x] | view3.rb:7:9:7:10 | @x | nodes | main.rb:3:9:3:9 | x | semmle.label | x | | main.rb:3:13:3:21 | call to source | semmle.label | call to source | -| main.rb:4:9:4:12 | view [@x] | semmle.label | view [@x] | -| main.rb:4:16:4:27 | call to new [@x] | semmle.label | call to new [@x] | +| main.rb:4:9:4:12 | view : View1 [@x] | semmle.label | view : View1 [@x] | +| main.rb:4:16:4:27 | call to new : View1 [@x] | semmle.label | call to new : View1 [@x] | | main.rb:4:26:4:26 | x | semmle.label | x | -| main.rb:5:16:5:19 | view [@x] | semmle.label | view [@x] | +| main.rb:5:16:5:19 | view : View1 [@x] | semmle.label | view : View1 [@x] | | main.rb:10:16:10:19 | [post] view [@x] | semmle.label | [post] view [@x] | | main.rb:11:9:11:12 | view [@x] | semmle.label | view [@x] | | main.rb:15:9:15:9 | x | semmle.label | x | | main.rb:15:13:15:21 | call to source | semmle.label | call to source | -| main.rb:16:9:16:12 | view [@x] | semmle.label | view [@x] | -| main.rb:16:16:16:27 | call to new [@x] | semmle.label | call to new [@x] | +| main.rb:16:9:16:12 | view : View3 [@x] | semmle.label | view : View3 [@x] | +| main.rb:16:16:16:27 | call to new : View3 [@x] | semmle.label | call to new : View3 [@x] | | main.rb:16:26:16:26 | x | semmle.label | x | -| main.rb:17:16:17:19 | view [@x] | semmle.label | view [@x] | -| view1.html.erb:2:5:2:9 | self [@x] | semmle.label | self [@x] | -| view1.html.erb:2:5:8:1 | self in view1.html.erb [@x] | semmle.label | self in view1.html.erb [@x] | +| main.rb:17:16:17:19 | view : View3 [@x] | semmle.label | view : View3 [@x] | +| view1.html.erb:2:5:2:9 | self : View1 [@x] | semmle.label | self : View1 [@x] | +| view1.html.erb:2:5:8:1 | self in view1.html.erb : View1 [@x] | semmle.label | self in view1.html.erb : View1 [@x] | | view1.html.erb:6:1:6:14 | [post] self [@x] | semmle.label | [post] self [@x] | | view1.html.erb:6:5:6:13 | call to source | semmle.label | call to source | +| view1.html.erb:7:1:7:5 | self : View1 [@x] | semmle.label | self : View1 [@x] | | view1.html.erb:7:1:7:5 | self [@x] | semmle.label | self [@x] | -| view1.html.erb:7:1:7:5 | self [@x] | semmle.label | self [@x] | -| view1.rb:5:20:5:20 | x | semmle.label | x | -| view1.rb:6:9:6:10 | [post] self [@x] | semmle.label | [post] self [@x] | -| view1.rb:6:14:6:14 | x | semmle.label | x | -| view1.rb:9:5:11:7 | self in foo [@x] | semmle.label | self in foo [@x] | -| view1.rb:10:14:10:15 | @x | semmle.label | @x | -| view1.rb:10:14:10:15 | self [@x] | semmle.label | self [@x] | -| view1.rb:13:13:13:13 | x | semmle.label | x | -| view1.rb:14:9:14:10 | [post] self [@x] | semmle.label | [post] self [@x] | -| view1.rb:14:14:14:14 | x | semmle.label | x | +| view1.rb:6:5:8:7 | self in foo : View1 [@x] | semmle.label | self in foo : View1 [@x] | +| view1.rb:7:14:7:15 | @x | semmle.label | @x | +| view1.rb:7:14:7:15 | self : View1 [@x] | semmle.label | self : View1 [@x] | +| view1.rb:10:13:10:13 | x | semmle.label | x | +| view1.rb:11:9:11:10 | [post] self [@x] | semmle.label | [post] self [@x] | +| view1.rb:11:14:11:14 | x | semmle.label | x | | view2.html.erb:3:1:3:14 | [post] self [@x] | semmle.label | [post] self [@x] | | view2.html.erb:3:5:3:13 | call to source | semmle.label | call to source | -| view2.rb:2:5:4:7 | self in foo [@x] | semmle.label | self in foo [@x] | +| view2.rb:2:5:4:7 | self in foo : View2 [@x] | semmle.label | self in foo : View2 [@x] | | view2.rb:3:14:3:15 | @x | semmle.label | @x | -| view2.rb:3:14:3:15 | self [@x] | semmle.label | self [@x] | +| view2.rb:3:14:3:15 | self : View2 [@x] | semmle.label | self : View2 [@x] | | view2.rb:6:13:6:13 | x | semmle.label | x | | view2.rb:7:9:7:10 | [post] self [@x] | semmle.label | [post] self [@x] | | view2.rb:7:14:7:14 | x | semmle.label | x | -| view3.html.erb:3:1:4:1 | self in view3.html.erb [@x] | semmle.label | self in view3.html.erb [@x] | +| view3.html.erb:3:1:4:1 | self in view3.html.erb : View3 [@x] | semmle.label | self in view3.html.erb : View3 [@x] | | view3.html.erb:3:6:3:8 | call to get | semmle.label | call to get | -| view3.html.erb:3:6:3:8 | self [@x] | semmle.label | self [@x] | -| view3.rb:2:20:2:20 | x | semmle.label | x | -| view3.rb:3:9:3:10 | [post] self [@x] | semmle.label | [post] self [@x] | -| view3.rb:3:14:3:14 | x | semmle.label | x | -| view3.rb:6:5:8:7 | self in get [@x] | semmle.label | self in get [@x] | +| view3.html.erb:3:6:3:8 | self : View3 [@x] | semmle.label | self : View3 [@x] | +| view3.rb:6:5:8:7 | self in get : View3 [@x] | semmle.label | self in get : View3 [@x] | | view3.rb:7:9:7:10 | @x | semmle.label | @x | -| view3.rb:7:9:7:10 | self [@x] | semmle.label | self [@x] | +| view3.rb:7:9:7:10 | self : View3 [@x] | semmle.label | self : View3 [@x] | subpaths -| main.rb:4:26:4:26 | x | view1.rb:5:20:5:20 | x | view1.rb:6:9:6:10 | [post] self [@x] | main.rb:4:16:4:27 | call to new [@x] | -| main.rb:16:26:16:26 | x | view3.rb:2:20:2:20 | x | view3.rb:3:9:3:10 | [post] self [@x] | main.rb:16:16:16:27 | call to new [@x] | -| view1.html.erb:6:5:6:13 | call to source | view1.rb:13:13:13:13 | x | view1.rb:14:9:14:10 | [post] self [@x] | view1.html.erb:6:1:6:14 | [post] self [@x] | +| view1.html.erb:6:5:6:13 | call to source | view1.rb:10:13:10:13 | x | view1.rb:11:9:11:10 | [post] self [@x] | view1.html.erb:6:1:6:14 | [post] self [@x] | | view2.html.erb:3:5:3:13 | call to source | view2.rb:6:13:6:13 | x | view2.rb:7:9:7:10 | [post] self [@x] | view2.html.erb:3:1:3:14 | [post] self [@x] | -| view3.html.erb:3:6:3:8 | self [@x] | view3.rb:6:5:8:7 | self in get [@x] | view3.rb:7:9:7:10 | @x | view3.html.erb:3:6:3:8 | call to get | +| view3.html.erb:3:6:3:8 | self : View3 [@x] | view3.rb:6:5:8:7 | self in get : View3 [@x] | view3.rb:7:9:7:10 | @x | view3.html.erb:3:6:3:8 | call to get | #select -| view1.rb:10:14:10:15 | @x | main.rb:3:13:3:21 | call to source | view1.rb:10:14:10:15 | @x | $@ | main.rb:3:13:3:21 | call to source | call to source | -| view1.rb:10:14:10:15 | @x | view1.html.erb:6:5:6:13 | call to source | view1.rb:10:14:10:15 | @x | $@ | view1.html.erb:6:5:6:13 | call to source | call to source | +| view1.rb:7:14:7:15 | @x | main.rb:3:13:3:21 | call to source | view1.rb:7:14:7:15 | @x | $@ | main.rb:3:13:3:21 | call to source | call to source | +| view1.rb:7:14:7:15 | @x | view1.html.erb:6:5:6:13 | call to source | view1.rb:7:14:7:15 | @x | $@ | view1.html.erb:6:5:6:13 | call to source | call to source | | view2.rb:3:14:3:15 | @x | view2.html.erb:3:5:3:13 | call to source | view2.rb:3:14:3:15 | @x | $@ | view2.html.erb:3:5:3:13 | call to source | call to source | | view3.html.erb:3:6:3:8 | call to get | main.rb:15:13:15:21 | call to source | view3.html.erb:3:6:3:8 | call to get | $@ | main.rb:15:13:15:21 | call to source | call to source | diff --git a/ruby/ql/test/library-tests/dataflow/erb/main.rb b/ruby/ql/test/library-tests/dataflow/erb/main.rb index 84af8820399e..a19f5082c41e 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/main.rb +++ b/ruby/ql/test/library-tests/dataflow/erb/main.rb @@ -17,3 +17,6 @@ def run3 render(view) end end + +class ViewComponent::Base +end diff --git a/ruby/ql/test/library-tests/dataflow/erb/view1.rb b/ruby/ql/test/library-tests/dataflow/erb/view1.rb index d0c6a08dd8ff..32c3bc5d1c8a 100644 --- a/ruby/ql/test/library-tests/dataflow/erb/view1.rb +++ b/ruby/ql/test/library-tests/dataflow/erb/view1.rb @@ -1,6 +1,3 @@ -class ViewComponent::Base -end - class View1 < ViewComponent::Base def initialize(x) @x = x diff --git a/ruby/ql/test/library-tests/dataflow/global/Flow.expected b/ruby/ql/test/library-tests/dataflow/global/Flow.expected index bd8ad749d7dc..2716ec929ef1 100644 --- a/ruby/ql/test/library-tests/dataflow/global/Flow.expected +++ b/ruby/ql/test/library-tests/dataflow/global/Flow.expected @@ -37,9 +37,12 @@ edges | captured_variables.rb:51:9:51:16 | call to taint | captured_variables.rb:49:16:52:3 | [post] do ... end [captured x] | | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:18:58:18 | x | | captured_variables.rb:58:18:58:18 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | -| captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:16:61:21 | self [@field] | +| captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:16:61:21 | self : Foo [@field] | +| captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:16:61:21 | self : Foo [@field] | | captured_variables.rb:61:16:61:21 | @field | captured_variables.rb:61:9:61:21 | return | -| captured_variables.rb:61:16:61:21 | self [@field] | captured_variables.rb:61:16:61:21 | @field | +| captured_variables.rb:61:16:61:21 | @field | captured_variables.rb:61:9:61:21 | return | +| captured_variables.rb:61:16:61:21 | self : Foo [@field] | captured_variables.rb:61:16:61:21 | @field | +| captured_variables.rb:61:16:61:21 | self : Foo [@field] | captured_variables.rb:61:16:61:21 | @field | | captured_variables.rb:66:1:66:3 | [post] foo [@field] | captured_variables.rb:67:16:70:3 | do ... end [captured foo, @field] | | captured_variables.rb:66:1:66:3 | [post] foo [@field] | captured_variables.rb:72:6:72:8 | foo [@field] | | captured_variables.rb:66:15:66:22 | call to taint | captured_variables.rb:57:19:57:19 | x | @@ -47,24 +50,24 @@ edges | captured_variables.rb:66:15:66:22 | call to taint | instance_variables.rb:10:19:10:19 | x | | captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | captured_variables.rb:72:6:72:8 | foo [@field] | | captured_variables.rb:67:16:70:3 | do ... end [captured foo, @field] | captured_variables.rb:68:10:68:12 | foo [@field] | -| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | +| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | | captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:68:10:68:22 | call to get_field | -| captured_variables.rb:68:10:68:12 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| captured_variables.rb:68:10:68:12 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | captured_variables.rb:69:5:69:7 | [post] foo [@field] | captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | | captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:57:19:57:19 | x | | captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:69:5:69:7 | [post] foo [@field] | | captured_variables.rb:69:19:69:26 | call to taint | instance_variables.rb:10:19:10:19 | x | -| captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | +| captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | | captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:72:6:72:18 | call to get_field | -| captured_variables.rb:72:6:72:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| captured_variables.rb:72:6:72:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] | captured_variables.rb:83:6:83:8 | foo [@field] | | captured_variables.rb:79:9:79:11 | [post] foo [@field] | captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] | | captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:57:19:57:19 | x | | captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:79:9:79:11 | [post] foo [@field] | | captured_variables.rb:79:23:79:30 | call to taint | instance_variables.rb:10:19:10:19 | x | -| captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | +| captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | | captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:83:6:83:18 | call to get_field | -| captured_variables.rb:83:6:83:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| captured_variables.rb:83:6:83:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:86:6:89:1 | -> { ... } [captured y] | | captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:90:1:90:2 | fn [captured y] | | captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:91:6:91:6 | y | @@ -99,27 +102,30 @@ edges | captured_variables.rb:149:5:151:7 | &block [captured self, @x] | captured_variables.rb:154:14:154:15 | self [@x] | | captured_variables.rb:153:14:155:7 | do ... end [captured self, @x] | captured_variables.rb:149:5:151:7 | &block [captured self, @x] | | captured_variables.rb:154:14:154:15 | self [@x] | captured_variables.rb:154:14:154:15 | @x | -| captured_variables.rb:160:9:160:10 | [post] self [@x] | captured_variables.rb:174:1:174:24 | call to new [@x] | +| captured_variables.rb:160:9:160:10 | [post] self [@x] | captured_variables.rb:174:1:174:24 | call to new : CaptureInstanceSelf1 [@x] | | captured_variables.rb:160:14:160:22 | call to taint | captured_variables.rb:160:9:160:10 | [post] self [@x] | -| captured_variables.rb:163:5:165:7 | &block [captured self, @x] | captured_variables.rb:169:18:169:19 | self [@x] | -| captured_variables.rb:167:5:171:7 | self in baz [@x] | captured_variables.rb:168:18:170:11 | do ... end [captured self, @x] | +| captured_variables.rb:163:5:165:7 | &block [captured self, @x] | captured_variables.rb:169:18:169:19 | self : CaptureInstanceSelf1 [@x] | +| captured_variables.rb:167:5:171:7 | self in baz : CaptureInstanceSelf1 [@x] | captured_variables.rb:168:18:170:11 | do ... end [captured self, @x] | | captured_variables.rb:168:18:170:11 | do ... end [captured self, @x] | captured_variables.rb:163:5:165:7 | &block [captured self, @x] | -| captured_variables.rb:169:18:169:19 | self [@x] | captured_variables.rb:169:18:169:19 | @x | -| captured_variables.rb:174:1:174:24 | call to new [@x] | captured_variables.rb:167:5:171:7 | self in baz [@x] | +| captured_variables.rb:169:18:169:19 | self : CaptureInstanceSelf1 [@x] | captured_variables.rb:169:18:169:19 | @x | +| captured_variables.rb:174:1:174:24 | call to new : CaptureInstanceSelf1 [@x] | captured_variables.rb:167:5:171:7 | self in baz : CaptureInstanceSelf1 [@x] | | captured_variables.rb:178:9:178:10 | [post] self [@x] | captured_variables.rb:193:1:193:1 | [post] c [@x] | | captured_variables.rb:178:14:178:22 | call to taint | captured_variables.rb:178:9:178:10 | [post] self [@x] | -| captured_variables.rb:181:5:183:7 | &block [captured self, @x] | captured_variables.rb:187:18:187:19 | self [@x] | -| captured_variables.rb:185:5:189:7 | self in baz [@x] | captured_variables.rb:186:18:188:11 | do ... end [captured self, @x] | +| captured_variables.rb:181:5:183:7 | &block [captured self, @x] | captured_variables.rb:187:18:187:19 | self : CaptureInstanceSelf2 [@x] | +| captured_variables.rb:185:5:189:7 | self in baz : CaptureInstanceSelf2 [@x] | captured_variables.rb:186:18:188:11 | do ... end [captured self, @x] | | captured_variables.rb:186:18:188:11 | do ... end [captured self, @x] | captured_variables.rb:181:5:183:7 | &block [captured self, @x] | -| captured_variables.rb:187:18:187:19 | self [@x] | captured_variables.rb:187:18:187:19 | @x | +| captured_variables.rb:187:18:187:19 | self : CaptureInstanceSelf2 [@x] | captured_variables.rb:187:18:187:19 | @x | | captured_variables.rb:193:1:193:1 | [post] c [@x] | captured_variables.rb:194:1:194:1 | c [@x] | -| captured_variables.rb:194:1:194:1 | c [@x] | captured_variables.rb:185:5:189:7 | self in baz [@x] | +| captured_variables.rb:194:1:194:1 | c [@x] | captured_variables.rb:185:5:189:7 | self in baz : CaptureInstanceSelf2 [@x] | | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:18:11:18 | x | | instance_variables.rb:11:18:11:18 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | -| instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:16:14:21 | self [@field] | +| instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:16:14:21 | self : Foo [@field] | +| instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:16:14:21 | self : Foo [@field] | +| instance_variables.rb:14:16:14:21 | @field | instance_variables.rb:14:9:14:21 | return | | instance_variables.rb:14:16:14:21 | @field | instance_variables.rb:14:9:14:21 | return | -| instance_variables.rb:14:16:14:21 | self [@field] | instance_variables.rb:14:16:14:21 | @field | -| instance_variables.rb:16:5:18:7 | self in inc_field [@field] | instance_variables.rb:17:9:17:14 | [post] self [@field] | +| instance_variables.rb:14:16:14:21 | self : Foo [@field] | instance_variables.rb:14:16:14:21 | @field | +| instance_variables.rb:14:16:14:21 | self : Foo [@field] | instance_variables.rb:14:16:14:21 | @field | +| instance_variables.rb:16:5:18:7 | self in inc_field : Foo [@field] | instance_variables.rb:17:9:17:14 | [post] self [@field] | | instance_variables.rb:17:9:17:14 | [post] self [@field] | instance_variables.rb:17:9:17:14 | [post] self [@field] | | instance_variables.rb:19:5:19:8 | [post] self [@foo] | instance_variables.rb:20:10:20:13 | self [@foo] | | instance_variables.rb:19:12:19:21 | call to taint | instance_variables.rb:19:5:19:8 | [post] self [@foo] | @@ -135,39 +141,39 @@ edges | instance_variables.rb:32:13:32:21 | call to taint | instance_variables.rb:22:20:22:24 | field | | instance_variables.rb:32:13:32:21 | call to taint | instance_variables.rb:48:20:48:20 | x | | instance_variables.rb:33:13:33:13 | x | instance_variables.rb:22:20:22:24 | field | -| instance_variables.rb:33:13:33:13 | x | instance_variables.rb:33:9:33:14 | call to new [@field] | -| instance_variables.rb:36:10:36:23 | call to new [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:36:10:36:23 | call to new [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | -| instance_variables.rb:36:10:36:23 | call to new [@field] | instance_variables.rb:36:10:36:33 | call to get_field | +| instance_variables.rb:33:13:33:13 | x | instance_variables.rb:33:9:33:14 | call to new : Foo [@field] | +| instance_variables.rb:36:10:36:23 | call to new : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:36:10:36:23 | call to new : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | +| instance_variables.rb:36:10:36:23 | call to new : Foo [@field] | instance_variables.rb:36:10:36:33 | call to get_field | | instance_variables.rb:36:14:36:22 | call to taint | instance_variables.rb:22:20:22:24 | field | -| instance_variables.rb:36:14:36:22 | call to taint | instance_variables.rb:36:10:36:23 | call to new [@field] | -| instance_variables.rb:39:6:39:23 | call to bar [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:39:6:39:23 | call to bar [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | -| instance_variables.rb:39:6:39:23 | call to bar [@field] | instance_variables.rb:39:6:39:33 | call to get_field | +| instance_variables.rb:36:14:36:22 | call to taint | instance_variables.rb:36:10:36:23 | call to new : Foo [@field] | +| instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | +| instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | instance_variables.rb:39:6:39:33 | call to get_field | | instance_variables.rb:39:14:39:22 | call to taint | instance_variables.rb:31:18:31:18 | x | -| instance_variables.rb:39:14:39:22 | call to taint | instance_variables.rb:39:6:39:23 | call to bar [@field] | +| instance_variables.rb:39:14:39:22 | call to taint | instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | | instance_variables.rb:43:9:43:17 | call to taint | instance_variables.rb:121:7:121:24 | call to new | | instance_variables.rb:48:20:48:20 | x | instance_variables.rb:49:14:49:14 | x | | instance_variables.rb:54:1:54:3 | [post] foo [@field] | instance_variables.rb:55:6:55:8 | foo [@field] | | instance_variables.rb:54:15:54:23 | call to taint | captured_variables.rb:57:19:57:19 | x | | instance_variables.rb:54:15:54:23 | call to taint | instance_variables.rb:10:19:10:19 | x | | instance_variables.rb:54:15:54:23 | call to taint | instance_variables.rb:54:1:54:3 | [post] foo [@field] | -| instance_variables.rb:55:6:55:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:55:6:55:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:55:6:55:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:55:6:55:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:55:6:55:8 | foo [@field] | instance_variables.rb:55:6:55:18 | call to get_field | | instance_variables.rb:58:1:58:3 | [post] bar [@field] | instance_variables.rb:59:6:59:8 | bar [@field] | | instance_variables.rb:58:15:58:22 | call to taint | captured_variables.rb:57:19:57:19 | x | | instance_variables.rb:58:15:58:22 | call to taint | instance_variables.rb:10:19:10:19 | x | | instance_variables.rb:58:15:58:22 | call to taint | instance_variables.rb:58:1:58:3 | [post] bar [@field] | -| instance_variables.rb:59:6:59:8 | bar [@field] | instance_variables.rb:16:5:18:7 | self in inc_field [@field] | +| instance_variables.rb:59:6:59:8 | bar [@field] | instance_variables.rb:16:5:18:7 | self in inc_field : Foo [@field] | | instance_variables.rb:59:6:59:8 | bar [@field] | instance_variables.rb:59:6:59:18 | call to inc_field | | instance_variables.rb:62:1:62:4 | [post] foo1 [@field] | instance_variables.rb:63:6:63:9 | foo1 [@field] | | instance_variables.rb:62:14:62:22 | call to taint | instance_variables.rb:62:1:62:4 | [post] foo1 [@field] | | instance_variables.rb:63:6:63:9 | foo1 [@field] | instance_variables.rb:63:6:63:15 | call to field | | instance_variables.rb:66:1:66:4 | [post] foo2 [@field] | instance_variables.rb:67:6:67:9 | foo2 [@field] | | instance_variables.rb:66:14:66:22 | call to taint | instance_variables.rb:66:1:66:4 | [post] foo2 [@field] | -| instance_variables.rb:67:6:67:9 | foo2 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:67:6:67:9 | foo2 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:67:6:67:9 | foo2 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:67:6:67:9 | foo2 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:67:6:67:9 | foo2 [@field] | instance_variables.rb:67:6:67:19 | call to get_field | | instance_variables.rb:70:1:70:4 | [post] foo3 [@field] | instance_variables.rb:71:6:71:9 | foo3 [@field] | | instance_variables.rb:70:1:70:4 | [post] foo3 [@field] | instance_variables.rb:83:6:83:9 | foo3 [@field] | @@ -180,21 +186,21 @@ edges | instance_variables.rb:78:18:78:26 | call to taint | captured_variables.rb:57:19:57:19 | x | | instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:10:19:10:19 | x | | instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:78:2:78:5 | [post] foo5 [@field] | -| instance_variables.rb:79:6:79:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:79:6:79:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:79:6:79:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:79:6:79:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:79:6:79:9 | foo5 [@field] | instance_variables.rb:79:6:79:19 | call to get_field | | instance_variables.rb:82:15:82:18 | [post] foo6 [@field] | instance_variables.rb:85:6:85:9 | foo6 [@field] | | instance_variables.rb:82:32:82:40 | call to taint | captured_variables.rb:57:19:57:19 | x | | instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:10:19:10:19 | x | | instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:82:15:82:18 | [post] foo6 [@field] | -| instance_variables.rb:83:6:83:9 | foo3 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:83:6:83:9 | foo3 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:83:6:83:9 | foo3 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:83:6:83:9 | foo3 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:83:6:83:9 | foo3 [@field] | instance_variables.rb:83:6:83:19 | call to get_field | -| instance_variables.rb:84:6:84:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:84:6:84:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:84:6:84:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:84:6:84:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:84:6:84:9 | foo5 [@field] | instance_variables.rb:84:6:84:19 | call to get_field | -| instance_variables.rb:85:6:85:9 | foo6 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:85:6:85:9 | foo6 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:85:6:85:9 | foo6 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:85:6:85:9 | foo6 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:85:6:85:9 | foo6 [@field] | instance_variables.rb:85:6:85:19 | call to get_field | | instance_variables.rb:89:15:89:18 | [post] foo7 [@field] | instance_variables.rb:90:6:90:9 | foo7 [@field] | | instance_variables.rb:89:25:89:28 | [post] foo8 [@field] | instance_variables.rb:91:6:91:9 | foo8 [@field] | @@ -202,11 +208,11 @@ edges | instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:10:19:10:19 | x | | instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:89:15:89:18 | [post] foo7 [@field] | | instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:89:25:89:28 | [post] foo8 [@field] | -| instance_variables.rb:90:6:90:9 | foo7 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:90:6:90:9 | foo7 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:90:6:90:9 | foo7 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:90:6:90:9 | foo7 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:90:6:90:9 | foo7 [@field] | instance_variables.rb:90:6:90:19 | call to get_field | -| instance_variables.rb:91:6:91:9 | foo8 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:91:6:91:9 | foo8 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:91:6:91:9 | foo8 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:91:6:91:9 | foo8 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:91:6:91:9 | foo8 [@field] | instance_variables.rb:91:6:91:19 | call to get_field | | instance_variables.rb:95:22:95:25 | [post] foo9 [@field] | instance_variables.rb:96:6:96:9 | foo9 [@field] | | instance_variables.rb:95:32:95:36 | [post] foo10 [@field] | instance_variables.rb:97:6:97:10 | foo10 [@field] | @@ -214,11 +220,11 @@ edges | instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:10:19:10:19 | x | | instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:95:22:95:25 | [post] foo9 [@field] | | instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:95:32:95:36 | [post] foo10 [@field] | -| instance_variables.rb:96:6:96:9 | foo9 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:96:6:96:9 | foo9 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:96:6:96:9 | foo9 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:96:6:96:9 | foo9 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:96:6:96:9 | foo9 [@field] | instance_variables.rb:96:6:96:19 | call to get_field | -| instance_variables.rb:97:6:97:10 | foo10 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:97:6:97:10 | foo10 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:97:6:97:10 | foo10 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:97:6:97:10 | foo10 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:97:6:97:10 | foo10 [@field] | instance_variables.rb:97:6:97:20 | call to get_field | | instance_variables.rb:100:5:100:5 | [post] x [@field] | instance_variables.rb:104:14:104:18 | [post] foo11 [@field] | | instance_variables.rb:100:5:100:5 | [post] x [@field] | instance_variables.rb:108:15:108:19 | [post] foo12 [@field] | @@ -227,29 +233,29 @@ edges | instance_variables.rb:100:17:100:25 | call to taint | instance_variables.rb:10:19:10:19 | x | | instance_variables.rb:100:17:100:25 | call to taint | instance_variables.rb:100:5:100:5 | [post] x [@field] | | instance_variables.rb:104:14:104:18 | [post] foo11 [@field] | instance_variables.rb:105:6:105:10 | foo11 [@field] | -| instance_variables.rb:105:6:105:10 | foo11 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:105:6:105:10 | foo11 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:105:6:105:10 | foo11 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:105:6:105:10 | foo11 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:105:6:105:10 | foo11 [@field] | instance_variables.rb:105:6:105:20 | call to get_field | | instance_variables.rb:108:15:108:19 | [post] foo12 [@field] | instance_variables.rb:109:6:109:10 | foo12 [@field] | -| instance_variables.rb:109:6:109:10 | foo12 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:109:6:109:10 | foo12 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:109:6:109:10 | foo12 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:109:6:109:10 | foo12 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:109:6:109:10 | foo12 [@field] | instance_variables.rb:109:6:109:20 | call to get_field | | instance_variables.rb:113:22:113:26 | [post] foo13 [@field] | instance_variables.rb:114:6:114:10 | foo13 [@field] | -| instance_variables.rb:114:6:114:10 | foo13 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:114:6:114:10 | foo13 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:114:6:114:10 | foo13 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:114:6:114:10 | foo13 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:114:6:114:10 | foo13 [@field] | instance_variables.rb:114:6:114:20 | call to get_field | -| instance_variables.rb:116:1:116:5 | foo15 [@field] | instance_variables.rb:117:6:117:10 | foo15 [@field] | -| instance_variables.rb:116:9:116:26 | call to new [@field] | instance_variables.rb:116:1:116:5 | foo15 [@field] | +| instance_variables.rb:116:1:116:5 | foo15 : Foo [@field] | instance_variables.rb:117:6:117:10 | foo15 : Foo [@field] | +| instance_variables.rb:116:9:116:26 | call to new : Foo [@field] | instance_variables.rb:116:1:116:5 | foo15 : Foo [@field] | | instance_variables.rb:116:17:116:25 | call to taint | instance_variables.rb:22:20:22:24 | field | -| instance_variables.rb:116:17:116:25 | call to taint | instance_variables.rb:116:9:116:26 | call to new [@field] | -| instance_variables.rb:117:6:117:10 | foo15 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:117:6:117:10 | foo15 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | -| instance_variables.rb:117:6:117:10 | foo15 [@field] | instance_variables.rb:117:6:117:20 | call to get_field | +| instance_variables.rb:116:17:116:25 | call to taint | instance_variables.rb:116:9:116:26 | call to new : Foo [@field] | +| instance_variables.rb:117:6:117:10 | foo15 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:117:6:117:10 | foo15 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | +| instance_variables.rb:117:6:117:10 | foo15 : Foo [@field] | instance_variables.rb:117:6:117:20 | call to get_field | | instance_variables.rb:119:6:119:10 | [post] foo16 [@field] | instance_variables.rb:120:6:120:10 | foo16 [@field] | | instance_variables.rb:119:28:119:36 | call to taint | instance_variables.rb:27:25:27:29 | field | | instance_variables.rb:119:28:119:36 | call to taint | instance_variables.rb:119:6:119:10 | [post] foo16 [@field] | -| instance_variables.rb:120:6:120:10 | foo16 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | -| instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | +| instance_variables.rb:120:6:120:10 | foo16 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | +| instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | | instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:120:6:120:20 | call to get_field | | instance_variables.rb:121:1:121:3 | bar | instance_variables.rb:122:6:122:8 | bar | | instance_variables.rb:121:7:121:24 | call to new | instance_variables.rb:121:1:121:3 | bar | @@ -296,10 +302,14 @@ nodes | captured_variables.rb:57:19:57:19 | x | semmle.label | x | | captured_variables.rb:58:9:58:14 | [post] self [@field] | semmle.label | [post] self [@field] | | captured_variables.rb:58:18:58:18 | x | semmle.label | x | -| captured_variables.rb:60:5:62:7 | self in get_field [@field] | semmle.label | self in get_field [@field] | +| captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | semmle.label | self in get_field : Foo [@field] | +| captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | semmle.label | self in get_field : Foo [@field] | +| captured_variables.rb:61:9:61:21 | return | semmle.label | return | | captured_variables.rb:61:9:61:21 | return | semmle.label | return | | captured_variables.rb:61:16:61:21 | @field | semmle.label | @field | -| captured_variables.rb:61:16:61:21 | self [@field] | semmle.label | self [@field] | +| captured_variables.rb:61:16:61:21 | @field | semmle.label | @field | +| captured_variables.rb:61:16:61:21 | self : Foo [@field] | semmle.label | self : Foo [@field] | +| captured_variables.rb:61:16:61:21 | self : Foo [@field] | semmle.label | self : Foo [@field] | | captured_variables.rb:66:1:66:3 | [post] foo [@field] | semmle.label | [post] foo [@field] | | captured_variables.rb:66:15:66:22 | call to taint | semmle.label | call to taint | | captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | semmle.label | [post] do ... end [captured foo, @field] | @@ -354,28 +364,32 @@ nodes | captured_variables.rb:160:9:160:10 | [post] self [@x] | semmle.label | [post] self [@x] | | captured_variables.rb:160:14:160:22 | call to taint | semmle.label | call to taint | | captured_variables.rb:163:5:165:7 | &block [captured self, @x] | semmle.label | &block [captured self, @x] | -| captured_variables.rb:167:5:171:7 | self in baz [@x] | semmle.label | self in baz [@x] | +| captured_variables.rb:167:5:171:7 | self in baz : CaptureInstanceSelf1 [@x] | semmle.label | self in baz : CaptureInstanceSelf1 [@x] | | captured_variables.rb:168:18:170:11 | do ... end [captured self, @x] | semmle.label | do ... end [captured self, @x] | | captured_variables.rb:169:18:169:19 | @x | semmle.label | @x | -| captured_variables.rb:169:18:169:19 | self [@x] | semmle.label | self [@x] | -| captured_variables.rb:174:1:174:24 | call to new [@x] | semmle.label | call to new [@x] | +| captured_variables.rb:169:18:169:19 | self : CaptureInstanceSelf1 [@x] | semmle.label | self : CaptureInstanceSelf1 [@x] | +| captured_variables.rb:174:1:174:24 | call to new : CaptureInstanceSelf1 [@x] | semmle.label | call to new : CaptureInstanceSelf1 [@x] | | captured_variables.rb:178:9:178:10 | [post] self [@x] | semmle.label | [post] self [@x] | | captured_variables.rb:178:14:178:22 | call to taint | semmle.label | call to taint | | captured_variables.rb:181:5:183:7 | &block [captured self, @x] | semmle.label | &block [captured self, @x] | -| captured_variables.rb:185:5:189:7 | self in baz [@x] | semmle.label | self in baz [@x] | +| captured_variables.rb:185:5:189:7 | self in baz : CaptureInstanceSelf2 [@x] | semmle.label | self in baz : CaptureInstanceSelf2 [@x] | | captured_variables.rb:186:18:188:11 | do ... end [captured self, @x] | semmle.label | do ... end [captured self, @x] | | captured_variables.rb:187:18:187:19 | @x | semmle.label | @x | -| captured_variables.rb:187:18:187:19 | self [@x] | semmle.label | self [@x] | +| captured_variables.rb:187:18:187:19 | self : CaptureInstanceSelf2 [@x] | semmle.label | self : CaptureInstanceSelf2 [@x] | | captured_variables.rb:193:1:193:1 | [post] c [@x] | semmle.label | [post] c [@x] | | captured_variables.rb:194:1:194:1 | c [@x] | semmle.label | c [@x] | | instance_variables.rb:10:19:10:19 | x | semmle.label | x | | instance_variables.rb:11:9:11:14 | [post] self [@field] | semmle.label | [post] self [@field] | | instance_variables.rb:11:18:11:18 | x | semmle.label | x | -| instance_variables.rb:13:5:15:7 | self in get_field [@field] | semmle.label | self in get_field [@field] | +| instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | semmle.label | self in get_field : Foo [@field] | +| instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | semmle.label | self in get_field : Foo [@field] | +| instance_variables.rb:14:9:14:21 | return | semmle.label | return | | instance_variables.rb:14:9:14:21 | return | semmle.label | return | | instance_variables.rb:14:16:14:21 | @field | semmle.label | @field | -| instance_variables.rb:14:16:14:21 | self [@field] | semmle.label | self [@field] | -| instance_variables.rb:16:5:18:7 | self in inc_field [@field] | semmle.label | self in inc_field [@field] | +| instance_variables.rb:14:16:14:21 | @field | semmle.label | @field | +| instance_variables.rb:14:16:14:21 | self : Foo [@field] | semmle.label | self : Foo [@field] | +| instance_variables.rb:14:16:14:21 | self : Foo [@field] | semmle.label | self : Foo [@field] | +| instance_variables.rb:16:5:18:7 | self in inc_field : Foo [@field] | semmle.label | self in inc_field : Foo [@field] | | instance_variables.rb:17:9:17:14 | [post] self [@field] | semmle.label | [post] self [@field] | | instance_variables.rb:19:5:19:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | | instance_variables.rb:19:12:19:21 | call to taint | semmle.label | call to taint | @@ -391,12 +405,12 @@ nodes | instance_variables.rb:28:20:28:24 | field | semmle.label | field | | instance_variables.rb:31:18:31:18 | x | semmle.label | x | | instance_variables.rb:32:13:32:21 | call to taint | semmle.label | call to taint | -| instance_variables.rb:33:9:33:14 | call to new [@field] | semmle.label | call to new [@field] | +| instance_variables.rb:33:9:33:14 | call to new : Foo [@field] | semmle.label | call to new : Foo [@field] | | instance_variables.rb:33:13:33:13 | x | semmle.label | x | -| instance_variables.rb:36:10:36:23 | call to new [@field] | semmle.label | call to new [@field] | +| instance_variables.rb:36:10:36:23 | call to new : Foo [@field] | semmle.label | call to new : Foo [@field] | | instance_variables.rb:36:10:36:33 | call to get_field | semmle.label | call to get_field | | instance_variables.rb:36:14:36:22 | call to taint | semmle.label | call to taint | -| instance_variables.rb:39:6:39:23 | call to bar [@field] | semmle.label | call to bar [@field] | +| instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | semmle.label | call to bar : Foo [@field] | | instance_variables.rb:39:6:39:33 | call to get_field | semmle.label | call to get_field | | instance_variables.rb:39:14:39:22 | call to taint | semmle.label | call to taint | | instance_variables.rb:43:9:43:17 | call to taint | semmle.label | call to taint | @@ -459,10 +473,10 @@ nodes | instance_variables.rb:113:22:113:26 | [post] foo13 [@field] | semmle.label | [post] foo13 [@field] | | instance_variables.rb:114:6:114:10 | foo13 [@field] | semmle.label | foo13 [@field] | | instance_variables.rb:114:6:114:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:116:1:116:5 | foo15 [@field] | semmle.label | foo15 [@field] | -| instance_variables.rb:116:9:116:26 | call to new [@field] | semmle.label | call to new [@field] | +| instance_variables.rb:116:1:116:5 | foo15 : Foo [@field] | semmle.label | foo15 : Foo [@field] | +| instance_variables.rb:116:9:116:26 | call to new : Foo [@field] | semmle.label | call to new : Foo [@field] | | instance_variables.rb:116:17:116:25 | call to taint | semmle.label | call to taint | -| instance_variables.rb:117:6:117:10 | foo15 [@field] | semmle.label | foo15 [@field] | +| instance_variables.rb:117:6:117:10 | foo15 : Foo [@field] | semmle.label | foo15 : Foo [@field] | | instance_variables.rb:117:6:117:20 | call to get_field | semmle.label | call to get_field | | instance_variables.rb:119:6:119:10 | [post] foo16 [@field] | semmle.label | [post] foo16 [@field] | | instance_variables.rb:119:6:119:37 | call to call_initialize | semmle.label | call to call_initialize | @@ -477,79 +491,76 @@ subpaths | captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:22:28:22:28 | x | captured_variables.rb:23:5:25:5 | -> { ... } [captured x] | captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] | | captured_variables.rb:66:15:66:22 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | captured_variables.rb:66:1:66:3 | [post] foo [@field] | | captured_variables.rb:66:15:66:22 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | captured_variables.rb:66:1:66:3 | [post] foo [@field] | -| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:68:10:68:22 | call to get_field | -| captured_variables.rb:68:10:68:12 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:68:10:68:22 | call to get_field | +| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:68:10:68:22 | call to get_field | +| captured_variables.rb:68:10:68:12 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:68:10:68:22 | call to get_field | | captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | captured_variables.rb:69:5:69:7 | [post] foo [@field] | | captured_variables.rb:69:19:69:26 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | captured_variables.rb:69:5:69:7 | [post] foo [@field] | -| captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:72:6:72:18 | call to get_field | -| captured_variables.rb:72:6:72:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:72:6:72:18 | call to get_field | +| captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:72:6:72:18 | call to get_field | +| captured_variables.rb:72:6:72:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:72:6:72:18 | call to get_field | | captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | captured_variables.rb:79:9:79:11 | [post] foo [@field] | | captured_variables.rb:79:23:79:30 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | captured_variables.rb:79:9:79:11 | [post] foo [@field] | -| captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:83:6:83:18 | call to get_field | -| captured_variables.rb:83:6:83:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:83:6:83:18 | call to get_field | +| captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:83:6:83:18 | call to get_field | +| captured_variables.rb:83:6:83:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:83:6:83:18 | call to get_field | | captured_variables.rb:98:13:98:20 | call to taint | captured_variables.rb:93:17:93:17 | x | captured_variables.rb:94:5:96:5 | -> { ... } [captured x] | captured_variables.rb:98:1:98:21 | call to capture_arg [captured x] | | instance_variables.rb:28:20:28:24 | field | instance_variables.rb:22:20:22:24 | field | instance_variables.rb:23:9:23:14 | [post] self [@field] | instance_variables.rb:28:9:28:25 | [post] self [@field] | -| instance_variables.rb:33:13:33:13 | x | instance_variables.rb:22:20:22:24 | field | instance_variables.rb:23:9:23:14 | [post] self [@field] | instance_variables.rb:33:9:33:14 | call to new [@field] | -| instance_variables.rb:36:10:36:23 | call to new [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:36:10:36:33 | call to get_field | -| instance_variables.rb:36:10:36:23 | call to new [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:36:10:36:33 | call to get_field | -| instance_variables.rb:36:14:36:22 | call to taint | instance_variables.rb:22:20:22:24 | field | instance_variables.rb:23:9:23:14 | [post] self [@field] | instance_variables.rb:36:10:36:23 | call to new [@field] | -| instance_variables.rb:39:6:39:23 | call to bar [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:39:6:39:33 | call to get_field | -| instance_variables.rb:39:6:39:23 | call to bar [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:39:6:39:33 | call to get_field | -| instance_variables.rb:39:14:39:22 | call to taint | instance_variables.rb:31:18:31:18 | x | instance_variables.rb:33:9:33:14 | call to new [@field] | instance_variables.rb:39:6:39:23 | call to bar [@field] | +| instance_variables.rb:36:10:36:23 | call to new : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:36:10:36:33 | call to get_field | +| instance_variables.rb:36:10:36:23 | call to new : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:36:10:36:33 | call to get_field | +| instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:39:6:39:33 | call to get_field | +| instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:39:6:39:33 | call to get_field | +| instance_variables.rb:39:14:39:22 | call to taint | instance_variables.rb:31:18:31:18 | x | instance_variables.rb:33:9:33:14 | call to new : Foo [@field] | instance_variables.rb:39:6:39:23 | call to bar : Foo [@field] | | instance_variables.rb:54:15:54:23 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:54:1:54:3 | [post] foo [@field] | | instance_variables.rb:54:15:54:23 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:54:1:54:3 | [post] foo [@field] | -| instance_variables.rb:55:6:55:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:55:6:55:18 | call to get_field | -| instance_variables.rb:55:6:55:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:55:6:55:18 | call to get_field | +| instance_variables.rb:55:6:55:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:55:6:55:18 | call to get_field | +| instance_variables.rb:55:6:55:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:55:6:55:18 | call to get_field | | instance_variables.rb:58:15:58:22 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:58:1:58:3 | [post] bar [@field] | | instance_variables.rb:58:15:58:22 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:58:1:58:3 | [post] bar [@field] | -| instance_variables.rb:59:6:59:8 | bar [@field] | instance_variables.rb:16:5:18:7 | self in inc_field [@field] | instance_variables.rb:16:5:18:7 | self in inc_field [@field] | instance_variables.rb:59:6:59:18 | call to inc_field | -| instance_variables.rb:59:6:59:8 | bar [@field] | instance_variables.rb:16:5:18:7 | self in inc_field [@field] | instance_variables.rb:17:9:17:14 | [post] self [@field] | instance_variables.rb:59:6:59:18 | call to inc_field | -| instance_variables.rb:67:6:67:9 | foo2 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:67:6:67:19 | call to get_field | -| instance_variables.rb:67:6:67:9 | foo2 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:67:6:67:19 | call to get_field | +| instance_variables.rb:59:6:59:8 | bar [@field] | instance_variables.rb:16:5:18:7 | self in inc_field : Foo [@field] | instance_variables.rb:16:5:18:7 | self in inc_field : Foo [@field] | instance_variables.rb:59:6:59:18 | call to inc_field | +| instance_variables.rb:59:6:59:8 | bar [@field] | instance_variables.rb:16:5:18:7 | self in inc_field : Foo [@field] | instance_variables.rb:17:9:17:14 | [post] self [@field] | instance_variables.rb:59:6:59:18 | call to inc_field | +| instance_variables.rb:67:6:67:9 | foo2 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:67:6:67:19 | call to get_field | +| instance_variables.rb:67:6:67:9 | foo2 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:67:6:67:19 | call to get_field | | instance_variables.rb:70:16:70:24 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:70:1:70:4 | [post] foo3 [@field] | | instance_variables.rb:70:16:70:24 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:70:1:70:4 | [post] foo3 [@field] | | instance_variables.rb:78:18:78:26 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:78:2:78:5 | [post] foo5 [@field] | | instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:78:2:78:5 | [post] foo5 [@field] | -| instance_variables.rb:79:6:79:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:79:6:79:19 | call to get_field | -| instance_variables.rb:79:6:79:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:79:6:79:19 | call to get_field | +| instance_variables.rb:79:6:79:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:79:6:79:19 | call to get_field | +| instance_variables.rb:79:6:79:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:79:6:79:19 | call to get_field | | instance_variables.rb:82:32:82:40 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:82:15:82:18 | [post] foo6 [@field] | | instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:82:15:82:18 | [post] foo6 [@field] | -| instance_variables.rb:83:6:83:9 | foo3 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:83:6:83:19 | call to get_field | -| instance_variables.rb:83:6:83:9 | foo3 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:83:6:83:19 | call to get_field | -| instance_variables.rb:84:6:84:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:84:6:84:19 | call to get_field | -| instance_variables.rb:84:6:84:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:84:6:84:19 | call to get_field | -| instance_variables.rb:85:6:85:9 | foo6 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:85:6:85:19 | call to get_field | -| instance_variables.rb:85:6:85:9 | foo6 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:85:6:85:19 | call to get_field | +| instance_variables.rb:83:6:83:9 | foo3 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:83:6:83:19 | call to get_field | +| instance_variables.rb:83:6:83:9 | foo3 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:83:6:83:19 | call to get_field | +| instance_variables.rb:84:6:84:9 | foo5 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:84:6:84:19 | call to get_field | +| instance_variables.rb:84:6:84:9 | foo5 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:84:6:84:19 | call to get_field | +| instance_variables.rb:85:6:85:9 | foo6 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:85:6:85:19 | call to get_field | +| instance_variables.rb:85:6:85:9 | foo6 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:85:6:85:19 | call to get_field | | instance_variables.rb:89:45:89:53 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:89:15:89:18 | [post] foo7 [@field] | | instance_variables.rb:89:45:89:53 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:89:25:89:28 | [post] foo8 [@field] | | instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:89:15:89:18 | [post] foo7 [@field] | | instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:89:25:89:28 | [post] foo8 [@field] | -| instance_variables.rb:90:6:90:9 | foo7 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:90:6:90:19 | call to get_field | -| instance_variables.rb:90:6:90:9 | foo7 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:90:6:90:19 | call to get_field | -| instance_variables.rb:91:6:91:9 | foo8 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:91:6:91:19 | call to get_field | -| instance_variables.rb:91:6:91:9 | foo8 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:91:6:91:19 | call to get_field | +| instance_variables.rb:90:6:90:9 | foo7 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:90:6:90:19 | call to get_field | +| instance_variables.rb:90:6:90:9 | foo7 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:90:6:90:19 | call to get_field | +| instance_variables.rb:91:6:91:9 | foo8 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:91:6:91:19 | call to get_field | +| instance_variables.rb:91:6:91:9 | foo8 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:91:6:91:19 | call to get_field | | instance_variables.rb:95:53:95:61 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:95:22:95:25 | [post] foo9 [@field] | | instance_variables.rb:95:53:95:61 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:95:32:95:36 | [post] foo10 [@field] | | instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:95:22:95:25 | [post] foo9 [@field] | | instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:95:32:95:36 | [post] foo10 [@field] | -| instance_variables.rb:96:6:96:9 | foo9 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:96:6:96:19 | call to get_field | -| instance_variables.rb:96:6:96:9 | foo9 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:96:6:96:19 | call to get_field | -| instance_variables.rb:97:6:97:10 | foo10 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:97:6:97:20 | call to get_field | -| instance_variables.rb:97:6:97:10 | foo10 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:97:6:97:20 | call to get_field | +| instance_variables.rb:96:6:96:9 | foo9 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:96:6:96:19 | call to get_field | +| instance_variables.rb:96:6:96:9 | foo9 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:96:6:96:19 | call to get_field | +| instance_variables.rb:97:6:97:10 | foo10 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:97:6:97:20 | call to get_field | +| instance_variables.rb:97:6:97:10 | foo10 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:97:6:97:20 | call to get_field | | instance_variables.rb:100:17:100:25 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | instance_variables.rb:100:5:100:5 | [post] x [@field] | | instance_variables.rb:100:17:100:25 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | instance_variables.rb:100:5:100:5 | [post] x [@field] | -| instance_variables.rb:105:6:105:10 | foo11 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:105:6:105:20 | call to get_field | -| instance_variables.rb:105:6:105:10 | foo11 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:105:6:105:20 | call to get_field | -| instance_variables.rb:109:6:109:10 | foo12 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:109:6:109:20 | call to get_field | -| instance_variables.rb:109:6:109:10 | foo12 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:109:6:109:20 | call to get_field | -| instance_variables.rb:114:6:114:10 | foo13 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:114:6:114:20 | call to get_field | -| instance_variables.rb:114:6:114:10 | foo13 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:114:6:114:20 | call to get_field | -| instance_variables.rb:116:17:116:25 | call to taint | instance_variables.rb:22:20:22:24 | field | instance_variables.rb:23:9:23:14 | [post] self [@field] | instance_variables.rb:116:9:116:26 | call to new [@field] | -| instance_variables.rb:117:6:117:10 | foo15 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:117:6:117:20 | call to get_field | -| instance_variables.rb:117:6:117:10 | foo15 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:117:6:117:20 | call to get_field | +| instance_variables.rb:105:6:105:10 | foo11 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:105:6:105:20 | call to get_field | +| instance_variables.rb:105:6:105:10 | foo11 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:105:6:105:20 | call to get_field | +| instance_variables.rb:109:6:109:10 | foo12 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:109:6:109:20 | call to get_field | +| instance_variables.rb:109:6:109:10 | foo12 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:109:6:109:20 | call to get_field | +| instance_variables.rb:114:6:114:10 | foo13 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:114:6:114:20 | call to get_field | +| instance_variables.rb:114:6:114:10 | foo13 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:114:6:114:20 | call to get_field | +| instance_variables.rb:117:6:117:10 | foo15 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:117:6:117:20 | call to get_field | +| instance_variables.rb:117:6:117:10 | foo15 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:117:6:117:20 | call to get_field | | instance_variables.rb:119:28:119:36 | call to taint | instance_variables.rb:27:25:27:29 | field | instance_variables.rb:28:9:28:25 | [post] self [@field] | instance_variables.rb:119:6:119:10 | [post] foo16 [@field] | -| instance_variables.rb:120:6:120:10 | foo16 [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:120:6:120:20 | call to get_field | -| instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:120:6:120:20 | call to get_field | +| instance_variables.rb:120:6:120:10 | foo16 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:120:6:120:20 | call to get_field | +| instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:120:6:120:20 | call to get_field | #select | blocks.rb:8:10:8:14 | yield ... | blocks.rb:14:12:14:20 | call to source | blocks.rb:8:10:8:14 | yield ... | $@ | blocks.rb:14:12:14:20 | call to source | call to source | | captured_variables.rb:10:20:10:20 | x | captured_variables.rb:13:20:13:29 | call to taint | captured_variables.rb:10:20:10:20 | x | $@ | captured_variables.rb:13:20:13:29 | call to taint | call to taint | diff --git a/ruby/ql/test/library-tests/dataflow/type-flow/Flow.expected b/ruby/ql/test/library-tests/dataflow/type-flow/Flow.expected new file mode 100644 index 000000000000..4363f2324ef2 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/type-flow/Flow.expected @@ -0,0 +1,371 @@ +testFailures +edges +| types.rb:1:11:1:11 | x : C1 | types.rb:2:5:2:5 | x : C1 | +| types.rb:1:11:1:11 | x : C2 | types.rb:2:5:2:5 | x : C2 | +| types.rb:1:11:1:11 | x : C3 | types.rb:2:5:2:5 | x : C3 | +| types.rb:20:5:22:7 | self in call_foo : C1 | types.rb:21:13:21:16 | self : C1 | +| types.rb:20:5:22:7 | self in call_foo : C3 | types.rb:21:13:21:16 | self : C3 | +| types.rb:21:13:21:16 | self : C1 | types.rb:52:9:52:9 | x : C1 | +| types.rb:21:13:21:16 | self : C1 | types.rb:52:9:52:9 | x : C1 | +| types.rb:21:13:21:16 | self : C3 | types.rb:52:9:52:9 | x : C3 | +| types.rb:24:5:26:7 | self in call_bar : C1 | types.rb:25:13:25:16 | self : C1 | +| types.rb:24:5:26:7 | self in call_bar : C3 | types.rb:25:13:25:16 | self : C3 | +| types.rb:25:13:25:16 | self : C1 | types.rb:61:9:61:9 | x : C1 | +| types.rb:25:13:25:16 | self : C1 | types.rb:61:9:61:9 | x : C1 | +| types.rb:25:13:25:16 | self : C3 | types.rb:61:9:61:9 | x : C3 | +| types.rb:31:5:33:7 | self in call_maybe_sink : C1 | types.rb:32:9:32:18 | self : C1 | +| types.rb:31:5:33:7 | self in call_maybe_sink : C2 | types.rb:32:9:32:18 | self : C2 | +| types.rb:31:5:33:7 | self in call_maybe_sink : C3 | types.rb:32:9:32:18 | self : C3 | +| types.rb:32:9:32:18 | self : C1 | types.rb:41:5:43:7 | self in maybe_sink : C2 | +| types.rb:32:9:32:18 | self : C1 | types.rb:47:5:49:7 | self in maybe_sink : C3 | +| types.rb:32:9:32:18 | self : C2 | types.rb:41:5:43:7 | self in maybe_sink : C2 | +| types.rb:32:9:32:18 | self : C3 | types.rb:47:5:49:7 | self in maybe_sink : C3 | +| types.rb:35:5:37:7 | self in call_call_maybe_sink : C1 | types.rb:36:9:36:23 | self : C1 | +| types.rb:35:5:37:7 | self in call_call_maybe_sink : C2 | types.rb:36:9:36:23 | self : C2 | +| types.rb:35:5:37:7 | self in call_call_maybe_sink : C3 | types.rb:36:9:36:23 | self : C3 | +| types.rb:36:9:36:23 | self : C1 | types.rb:31:5:33:7 | self in call_maybe_sink : C1 | +| types.rb:36:9:36:23 | self : C2 | types.rb:31:5:33:7 | self in call_maybe_sink : C2 | +| types.rb:36:9:36:23 | self : C3 | types.rb:31:5:33:7 | self in call_maybe_sink : C3 | +| types.rb:41:5:43:7 | self in maybe_sink : C2 | types.rb:42:14:42:17 | self | +| types.rb:47:5:49:7 | self in maybe_sink : C3 | types.rb:48:14:48:17 | self | +| types.rb:52:9:52:9 | x : C1 | types.rb:55:18:55:18 | x | +| types.rb:52:9:52:9 | x : C3 | types.rb:55:18:55:18 | x | +| types.rb:61:9:61:9 | x : C1 | types.rb:63:18:63:19 | c3 : C3 | +| types.rb:61:9:61:9 | x : C3 | types.rb:63:18:63:19 | c3 : C3 | +| types.rb:63:18:63:19 | c3 : C3 | types.rb:64:18:64:19 | c3 | +| types.rb:71:5:71:19 | call to taint : C1 | types.rb:52:9:52:9 | x : C1 | +| types.rb:71:11:71:18 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | +| types.rb:71:11:71:18 | call to new : C1 | types.rb:71:5:71:19 | call to taint : C1 | +| types.rb:73:5:73:19 | call to taint : C3 | types.rb:52:9:52:9 | x : C3 | +| types.rb:73:11:73:18 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | +| types.rb:73:11:73:18 | call to new : C3 | types.rb:73:5:73:19 | call to taint : C3 | +| types.rb:75:1:75:15 | call to taint : C1 | types.rb:20:5:22:7 | self in call_foo : C1 | +| types.rb:75:7:75:14 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | +| types.rb:75:7:75:14 | call to new : C1 | types.rb:75:1:75:15 | call to taint : C1 | +| types.rb:77:1:77:15 | call to taint : C3 | types.rb:20:5:22:7 | self in call_foo : C3 | +| types.rb:77:7:77:14 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | +| types.rb:77:7:77:14 | call to new : C3 | types.rb:77:1:77:15 | call to taint : C3 | +| types.rb:79:5:79:19 | call to taint : C1 | types.rb:61:9:61:9 | x : C1 | +| types.rb:79:11:79:18 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | +| types.rb:79:11:79:18 | call to new : C1 | types.rb:79:5:79:19 | call to taint : C1 | +| types.rb:81:5:81:19 | call to taint : C3 | types.rb:61:9:61:9 | x : C3 | +| types.rb:81:11:81:18 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | +| types.rb:81:11:81:18 | call to new : C3 | types.rb:81:5:81:19 | call to taint : C3 | +| types.rb:83:1:83:15 | call to taint : C1 | types.rb:24:5:26:7 | self in call_bar : C1 | +| types.rb:83:7:83:14 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | +| types.rb:83:7:83:14 | call to new : C1 | types.rb:83:1:83:15 | call to taint : C1 | +| types.rb:85:1:85:16 | call to taint : C3 | types.rb:24:5:26:7 | self in call_bar : C3 | +| types.rb:85:7:85:15 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | +| types.rb:85:7:85:15 | call to new : C3 | types.rb:85:1:85:16 | call to taint : C3 | +| types.rb:87:1:87:16 | call to taint : C1 | types.rb:35:5:37:7 | self in call_call_maybe_sink : C1 | +| types.rb:87:7:87:15 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | +| types.rb:87:7:87:15 | call to new : C1 | types.rb:87:1:87:16 | call to taint : C1 | +| types.rb:88:1:88:16 | call to taint : C2 | types.rb:35:5:37:7 | self in call_call_maybe_sink : C2 | +| types.rb:88:7:88:15 | call to new : C2 | types.rb:1:11:1:11 | x : C2 | +| types.rb:88:7:88:15 | call to new : C2 | types.rb:88:1:88:16 | call to taint : C2 | +| types.rb:89:1:89:16 | call to taint : C3 | types.rb:35:5:37:7 | self in call_call_maybe_sink : C3 | +| types.rb:89:7:89:15 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | +| types.rb:89:7:89:15 | call to new : C3 | types.rb:89:1:89:16 | call to taint : C3 | +nodes +| types.rb:1:11:1:11 | x : C1 | semmle.label | x : C1 | +| types.rb:1:11:1:11 | x : C2 | semmle.label | x : C2 | +| types.rb:1:11:1:11 | x : C3 | semmle.label | x : C3 | +| types.rb:2:5:2:5 | x : C1 | semmle.label | x : C1 | +| types.rb:2:5:2:5 | x : C2 | semmle.label | x : C2 | +| types.rb:2:5:2:5 | x : C3 | semmle.label | x : C3 | +| types.rb:20:5:22:7 | self in call_foo : C1 | semmle.label | self in call_foo : C1 | +| types.rb:20:5:22:7 | self in call_foo : C3 | semmle.label | self in call_foo : C3 | +| types.rb:21:13:21:16 | self : C1 | semmle.label | self : C1 | +| types.rb:21:13:21:16 | self : C1 | semmle.label | self : C1 | +| types.rb:21:13:21:16 | self : C3 | semmle.label | self : C3 | +| types.rb:24:5:26:7 | self in call_bar : C1 | semmle.label | self in call_bar : C1 | +| types.rb:24:5:26:7 | self in call_bar : C3 | semmle.label | self in call_bar : C3 | +| types.rb:25:13:25:16 | self : C1 | semmle.label | self : C1 | +| types.rb:25:13:25:16 | self : C1 | semmle.label | self : C1 | +| types.rb:25:13:25:16 | self : C3 | semmle.label | self : C3 | +| types.rb:31:5:33:7 | self in call_maybe_sink : C1 | semmle.label | self in call_maybe_sink : C1 | +| types.rb:31:5:33:7 | self in call_maybe_sink : C2 | semmle.label | self in call_maybe_sink : C2 | +| types.rb:31:5:33:7 | self in call_maybe_sink : C3 | semmle.label | self in call_maybe_sink : C3 | +| types.rb:32:9:32:18 | self : C1 | semmle.label | self : C1 | +| types.rb:32:9:32:18 | self : C2 | semmle.label | self : C2 | +| types.rb:32:9:32:18 | self : C3 | semmle.label | self : C3 | +| types.rb:35:5:37:7 | self in call_call_maybe_sink : C1 | semmle.label | self in call_call_maybe_sink : C1 | +| types.rb:35:5:37:7 | self in call_call_maybe_sink : C2 | semmle.label | self in call_call_maybe_sink : C2 | +| types.rb:35:5:37:7 | self in call_call_maybe_sink : C3 | semmle.label | self in call_call_maybe_sink : C3 | +| types.rb:36:9:36:23 | self : C1 | semmle.label | self : C1 | +| types.rb:36:9:36:23 | self : C2 | semmle.label | self : C2 | +| types.rb:36:9:36:23 | self : C3 | semmle.label | self : C3 | +| types.rb:41:5:43:7 | self in maybe_sink : C2 | semmle.label | self in maybe_sink : C2 | +| types.rb:42:14:42:17 | self | semmle.label | self | +| types.rb:47:5:49:7 | self in maybe_sink : C3 | semmle.label | self in maybe_sink : C3 | +| types.rb:48:14:48:17 | self | semmle.label | self | +| types.rb:52:9:52:9 | x : C1 | semmle.label | x : C1 | +| types.rb:52:9:52:9 | x : C3 | semmle.label | x : C3 | +| types.rb:55:18:55:18 | x | semmle.label | x | +| types.rb:61:9:61:9 | x : C1 | semmle.label | x : C1 | +| types.rb:61:9:61:9 | x : C3 | semmle.label | x : C3 | +| types.rb:63:18:63:19 | c3 : C3 | semmle.label | c3 : C3 | +| types.rb:64:18:64:19 | c3 | semmle.label | c3 | +| types.rb:71:5:71:19 | call to taint : C1 | semmle.label | call to taint : C1 | +| types.rb:71:11:71:18 | call to new : C1 | semmle.label | call to new : C1 | +| types.rb:73:5:73:19 | call to taint : C3 | semmle.label | call to taint : C3 | +| types.rb:73:11:73:18 | call to new : C3 | semmle.label | call to new : C3 | +| types.rb:75:1:75:15 | call to taint : C1 | semmle.label | call to taint : C1 | +| types.rb:75:7:75:14 | call to new : C1 | semmle.label | call to new : C1 | +| types.rb:77:1:77:15 | call to taint : C3 | semmle.label | call to taint : C3 | +| types.rb:77:7:77:14 | call to new : C3 | semmle.label | call to new : C3 | +| types.rb:79:5:79:19 | call to taint : C1 | semmle.label | call to taint : C1 | +| types.rb:79:11:79:18 | call to new : C1 | semmle.label | call to new : C1 | +| types.rb:81:5:81:19 | call to taint : C3 | semmle.label | call to taint : C3 | +| types.rb:81:11:81:18 | call to new : C3 | semmle.label | call to new : C3 | +| types.rb:83:1:83:15 | call to taint : C1 | semmle.label | call to taint : C1 | +| types.rb:83:7:83:14 | call to new : C1 | semmle.label | call to new : C1 | +| types.rb:85:1:85:16 | call to taint : C3 | semmle.label | call to taint : C3 | +| types.rb:85:7:85:15 | call to new : C3 | semmle.label | call to new : C3 | +| types.rb:87:1:87:16 | call to taint : C1 | semmle.label | call to taint : C1 | +| types.rb:87:7:87:15 | call to new : C1 | semmle.label | call to new : C1 | +| types.rb:88:1:88:16 | call to taint : C2 | semmle.label | call to taint : C2 | +| types.rb:88:7:88:15 | call to new : C2 | semmle.label | call to new : C2 | +| types.rb:89:1:89:16 | call to taint : C3 | semmle.label | call to taint : C3 | +| types.rb:89:7:89:15 | call to new : C3 | semmle.label | call to new : C3 | +subpaths +| types.rb:71:11:71:18 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | types.rb:2:5:2:5 | x : C1 | types.rb:71:5:71:19 | call to taint : C1 | +| types.rb:73:11:73:18 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | types.rb:2:5:2:5 | x : C3 | types.rb:73:5:73:19 | call to taint : C3 | +| types.rb:75:7:75:14 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | types.rb:2:5:2:5 | x : C1 | types.rb:75:1:75:15 | call to taint : C1 | +| types.rb:77:7:77:14 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | types.rb:2:5:2:5 | x : C3 | types.rb:77:1:77:15 | call to taint : C3 | +| types.rb:79:11:79:18 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | types.rb:2:5:2:5 | x : C1 | types.rb:79:5:79:19 | call to taint : C1 | +| types.rb:81:11:81:18 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | types.rb:2:5:2:5 | x : C3 | types.rb:81:5:81:19 | call to taint : C3 | +| types.rb:83:7:83:14 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | types.rb:2:5:2:5 | x : C1 | types.rb:83:1:83:15 | call to taint : C1 | +| types.rb:85:7:85:15 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | types.rb:2:5:2:5 | x : C3 | types.rb:85:1:85:16 | call to taint : C3 | +| types.rb:87:7:87:15 | call to new : C1 | types.rb:1:11:1:11 | x : C1 | types.rb:2:5:2:5 | x : C1 | types.rb:87:1:87:16 | call to taint : C1 | +| types.rb:88:7:88:15 | call to new : C2 | types.rb:1:11:1:11 | x : C2 | types.rb:2:5:2:5 | x : C2 | types.rb:88:1:88:16 | call to taint : C2 | +| types.rb:89:7:89:15 | call to new : C3 | types.rb:1:11:1:11 | x : C3 | types.rb:2:5:2:5 | x : C3 | types.rb:89:1:89:16 | call to taint : C3 | +nodeType +| file://:0:0:0:0 | [summary param] * (position 0) in Array.[] | file://:0:0:0:0 | Array | +| file://:0:0:0:0 | [summary param] ** in Hash.[] | file://:0:0:0:0 | Hash | +| file://:0:0:0:0 | [summary param] position 0 in & | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] position 0 in + | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] position 0 in Hash[] | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] position 0 in \| | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] self in & | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] self in * | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] self in - | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] self in \| | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary param] self in assoc-unknown-arg | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in Hash[] | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[0].WithElement[0..] in Array() | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[0].WithElement[any] in Array.new | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[0].WithElement[any] in Array.try_convert | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[0].WithElement[any] in Hash.try_convert | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[0].WithElement[any] in Hash[] | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[self].WithElement[any] in *(splat) | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[self].WithElement[any] in **(hash-splat) | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[self].WithElement[any] in + | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] read: Argument[self].WithElement[any] in << | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: Argument[self] in << | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in & | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in * | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in *(splat) | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in + | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in - | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in << | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in Array() | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in Array.new | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in Hash[] | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in \| | file://:0:0:0:0 | [collection] | +| file://:0:0:0:0 | [summary] to write: ReturnValue in assoc-unknown-arg | file://:0:0:0:0 | [collection] | +| types.rb:1:1:3:3 | &block | file://:0:0:0:0 | Proc | +| types.rb:1:1:3:3 | self in taint | file://:0:0:0:0 | Object | +| types.rb:1:1:3:3 | synthetic splat parameter | file://:0:0:0:0 | Array | +| types.rb:1:1:3:3 | taint | file://:0:0:0:0 | Symbol | +| types.rb:1:1:89:38 | self (types.rb) | file://:0:0:0:0 | Object | +| types.rb:1:1:89:38 | self in types.rb | file://:0:0:0:0 | Object | +| types.rb:5:1:7:3 | &block | file://:0:0:0:0 | Proc | +| types.rb:5:1:7:3 | self (sink) | file://:0:0:0:0 | Object | +| types.rb:5:1:7:3 | self in sink | file://:0:0:0:0 | Object | +| types.rb:5:1:7:3 | sink | file://:0:0:0:0 | Symbol | +| types.rb:5:1:7:3 | synthetic splat parameter | file://:0:0:0:0 | Array | +| types.rb:6:5:6:31 | self | file://:0:0:0:0 | Object | +| types.rb:6:5:6:31 | synthetic splat argument | file://:0:0:0:0 | [splat] puts | +| types.rb:6:10:6:31 | "SINK: #{...}" | file://:0:0:0:0 | String | +| types.rb:12:5:14:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:12:5:14:7 | initialize | file://:0:0:0:0 | Symbol | +| types.rb:12:5:14:7 | self (initialize) | types.rb:9:1:38:3 | C1 | +| types.rb:12:5:14:7 | self in initialize | types.rb:9:1:38:3 | C1 | +| types.rb:12:5:14:7 | synthetic splat parameter | file://:0:0:0:0 | Array | +| types.rb:13:9:13:14 | self | types.rb:9:1:38:3 | C1 | +| types.rb:16:5:18:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:16:5:18:7 | get_field | file://:0:0:0:0 | Symbol | +| types.rb:16:5:18:7 | self (get_field) | types.rb:9:1:38:3 | C1 | +| types.rb:16:5:18:7 | self in get_field | types.rb:9:1:38:3 | C1 | +| types.rb:17:9:17:14 | self | types.rb:9:1:38:3 | C1 | +| types.rb:20:5:22:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:20:5:22:7 | call_foo | file://:0:0:0:0 | Symbol | +| types.rb:20:5:22:7 | self (call_foo) | types.rb:9:1:38:3 | C1 | +| types.rb:20:5:22:7 | self in call_foo | types.rb:9:1:38:3 | C1 | +| types.rb:21:9:21:17 | self | types.rb:9:1:38:3 | C1 | +| types.rb:21:9:21:17 | synthetic splat argument | file://:0:0:0:0 | [splat] foo | +| types.rb:21:13:21:16 | self | types.rb:9:1:38:3 | C1 | +| types.rb:24:5:26:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:24:5:26:7 | call_bar | file://:0:0:0:0 | Symbol | +| types.rb:24:5:26:7 | self (call_bar) | types.rb:9:1:38:3 | C1 | +| types.rb:24:5:26:7 | self in call_bar | types.rb:9:1:38:3 | C1 | +| types.rb:25:9:25:17 | self | types.rb:9:1:38:3 | C1 | +| types.rb:25:9:25:17 | synthetic splat argument | file://:0:0:0:0 | [splat] bar | +| types.rb:25:13:25:16 | self | types.rb:9:1:38:3 | C1 | +| types.rb:28:5:29:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:28:5:29:7 | maybe_sink | file://:0:0:0:0 | Symbol | +| types.rb:28:5:29:7 | self in maybe_sink | types.rb:9:1:38:3 | C1 | +| types.rb:31:5:33:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:31:5:33:7 | call_maybe_sink | file://:0:0:0:0 | Symbol | +| types.rb:31:5:33:7 | self (call_maybe_sink) | types.rb:9:1:38:3 | C1 | +| types.rb:31:5:33:7 | self in call_maybe_sink | types.rb:9:1:38:3 | C1 | +| types.rb:32:9:32:18 | self | types.rb:9:1:38:3 | C1 | +| types.rb:35:5:37:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:35:5:37:7 | call_call_maybe_sink | file://:0:0:0:0 | Symbol | +| types.rb:35:5:37:7 | self (call_call_maybe_sink) | types.rb:9:1:38:3 | C1 | +| types.rb:35:5:37:7 | self in call_call_maybe_sink | types.rb:9:1:38:3 | C1 | +| types.rb:36:9:36:23 | self | types.rb:9:1:38:3 | C1 | +| types.rb:41:5:43:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:41:5:43:7 | maybe_sink | file://:0:0:0:0 | Symbol | +| types.rb:41:5:43:7 | self (maybe_sink) | types.rb:40:1:44:3 | C2 | +| types.rb:41:5:43:7 | self in maybe_sink | types.rb:40:1:44:3 | C2 | +| types.rb:42:9:42:17 | self | types.rb:40:1:44:3 | C2 | +| types.rb:42:9:42:17 | synthetic splat argument | file://:0:0:0:0 | [splat] sink | +| types.rb:42:14:42:17 | self | types.rb:40:1:44:3 | C2 | +| types.rb:47:5:49:7 | &block | file://:0:0:0:0 | Proc | +| types.rb:47:5:49:7 | maybe_sink | file://:0:0:0:0 | Symbol | +| types.rb:47:5:49:7 | self (maybe_sink) | types.rb:46:1:50:3 | C3 | +| types.rb:47:5:49:7 | self in maybe_sink | types.rb:46:1:50:3 | C3 | +| types.rb:48:9:48:17 | self | types.rb:46:1:50:3 | C3 | +| types.rb:48:9:48:17 | synthetic splat argument | file://:0:0:0:0 | [splat] sink | +| types.rb:48:14:48:17 | self | types.rb:46:1:50:3 | C3 | +| types.rb:52:1:59:3 | &block | file://:0:0:0:0 | Proc | +| types.rb:52:1:59:3 | foo | file://:0:0:0:0 | Symbol | +| types.rb:52:1:59:3 | self (foo) | file://:0:0:0:0 | Object | +| types.rb:52:1:59:3 | self in foo | file://:0:0:0:0 | Object | +| types.rb:52:1:59:3 | synthetic splat parameter | file://:0:0:0:0 | Array | +| types.rb:55:13:55:19 | self | file://:0:0:0:0 | Object | +| types.rb:55:13:55:19 | synthetic splat argument | file://:0:0:0:0 | [splat] sink | +| types.rb:55:18:55:18 | x | types.rb:46:1:50:3 | C3 | +| types.rb:56:18:56:18 | x | types.rb:46:1:50:3 | C3 | +| types.rb:56:33:56:39 | self | file://:0:0:0:0 | Object | +| types.rb:56:33:56:39 | synthetic splat argument | file://:0:0:0:0 | [splat] sink | +| types.rb:56:38:56:38 | x | types.rb:40:1:44:3 | C2 | +| types.rb:61:1:69:3 | &block | file://:0:0:0:0 | Proc | +| types.rb:61:1:69:3 | bar | file://:0:0:0:0 | Symbol | +| types.rb:61:1:69:3 | self (bar) | file://:0:0:0:0 | Object | +| types.rb:61:1:69:3 | self in bar | file://:0:0:0:0 | Object | +| types.rb:61:1:69:3 | synthetic splat parameter | file://:0:0:0:0 | Array | +| types.rb:63:18:63:19 | c3 | types.rb:46:1:50:3 | C3 | +| types.rb:64:13:64:20 | self | file://:0:0:0:0 | Object | +| types.rb:64:13:64:20 | synthetic splat argument | file://:0:0:0:0 | [splat] sink | +| types.rb:64:18:64:19 | c3 | types.rb:46:1:50:3 | C3 | +| types.rb:65:18:65:19 | c3 | types.rb:46:1:50:3 | C3 | +| types.rb:65:34:65:41 | self | file://:0:0:0:0 | Object | +| types.rb:65:34:65:41 | synthetic splat argument | file://:0:0:0:0 | [splat] sink | +| types.rb:65:39:65:40 | c3 | types.rb:40:1:44:3 | C2 | +| types.rb:71:1:71:20 | self | file://:0:0:0:0 | Object | +| types.rb:71:1:71:20 | synthetic splat argument | file://:0:0:0:0 | [splat] foo | +| types.rb:71:5:71:19 | self | file://:0:0:0:0 | Object | +| types.rb:71:5:71:19 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:71:11:71:18 | call to new | types.rb:9:1:38:3 | C1 | +| types.rb:71:11:71:18 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:71:18:71:18 | 0 | file://:0:0:0:0 | Integer | +| types.rb:72:1:72:20 | self | file://:0:0:0:0 | Object | +| types.rb:72:1:72:20 | synthetic splat argument | file://:0:0:0:0 | [splat] foo | +| types.rb:72:5:72:19 | self | file://:0:0:0:0 | Object | +| types.rb:72:5:72:19 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:72:11:72:18 | call to new | types.rb:40:1:44:3 | C2 | +| types.rb:72:11:72:18 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:72:18:72:18 | 1 | file://:0:0:0:0 | Integer | +| types.rb:73:1:73:20 | self | file://:0:0:0:0 | Object | +| types.rb:73:1:73:20 | synthetic splat argument | file://:0:0:0:0 | [splat] foo | +| types.rb:73:5:73:19 | self | file://:0:0:0:0 | Object | +| types.rb:73:5:73:19 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:73:11:73:18 | call to new | types.rb:46:1:50:3 | C3 | +| types.rb:73:11:73:18 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:73:18:73:18 | 2 | file://:0:0:0:0 | Integer | +| types.rb:75:1:75:15 | self | file://:0:0:0:0 | Object | +| types.rb:75:1:75:15 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:75:7:75:14 | call to new | types.rb:9:1:38:3 | C1 | +| types.rb:75:7:75:14 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:75:14:75:14 | 3 | file://:0:0:0:0 | Integer | +| types.rb:76:1:76:15 | self | file://:0:0:0:0 | Object | +| types.rb:76:1:76:15 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:76:7:76:14 | call to new | types.rb:40:1:44:3 | C2 | +| types.rb:76:7:76:14 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:76:14:76:14 | 4 | file://:0:0:0:0 | Integer | +| types.rb:77:1:77:15 | self | file://:0:0:0:0 | Object | +| types.rb:77:1:77:15 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:77:7:77:14 | call to new | types.rb:46:1:50:3 | C3 | +| types.rb:77:7:77:14 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:77:14:77:14 | 5 | file://:0:0:0:0 | Integer | +| types.rb:79:1:79:20 | self | file://:0:0:0:0 | Object | +| types.rb:79:1:79:20 | synthetic splat argument | file://:0:0:0:0 | [splat] bar | +| types.rb:79:5:79:19 | self | file://:0:0:0:0 | Object | +| types.rb:79:5:79:19 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:79:11:79:18 | call to new | types.rb:9:1:38:3 | C1 | +| types.rb:79:11:79:18 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:79:18:79:18 | 6 | file://:0:0:0:0 | Integer | +| types.rb:80:1:80:20 | self | file://:0:0:0:0 | Object | +| types.rb:80:1:80:20 | synthetic splat argument | file://:0:0:0:0 | [splat] bar | +| types.rb:80:5:80:19 | self | file://:0:0:0:0 | Object | +| types.rb:80:5:80:19 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:80:11:80:18 | call to new | types.rb:40:1:44:3 | C2 | +| types.rb:80:11:80:18 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:80:18:80:18 | 7 | file://:0:0:0:0 | Integer | +| types.rb:81:1:81:20 | self | file://:0:0:0:0 | Object | +| types.rb:81:1:81:20 | synthetic splat argument | file://:0:0:0:0 | [splat] bar | +| types.rb:81:5:81:19 | self | file://:0:0:0:0 | Object | +| types.rb:81:5:81:19 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:81:11:81:18 | call to new | types.rb:46:1:50:3 | C3 | +| types.rb:81:11:81:18 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:81:18:81:18 | 8 | file://:0:0:0:0 | Integer | +| types.rb:83:1:83:15 | self | file://:0:0:0:0 | Object | +| types.rb:83:1:83:15 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:83:7:83:14 | call to new | types.rb:9:1:38:3 | C1 | +| types.rb:83:7:83:14 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:83:14:83:14 | 9 | file://:0:0:0:0 | Integer | +| types.rb:84:1:84:16 | self | file://:0:0:0:0 | Object | +| types.rb:84:1:84:16 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:84:7:84:15 | call to new | types.rb:40:1:44:3 | C2 | +| types.rb:84:7:84:15 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:84:14:84:15 | 10 | file://:0:0:0:0 | Integer | +| types.rb:85:1:85:16 | self | file://:0:0:0:0 | Object | +| types.rb:85:1:85:16 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:85:7:85:15 | call to new | types.rb:46:1:50:3 | C3 | +| types.rb:85:7:85:15 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:85:14:85:15 | 11 | file://:0:0:0:0 | Integer | +| types.rb:87:1:87:16 | self | file://:0:0:0:0 | Object | +| types.rb:87:1:87:16 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:87:7:87:15 | call to new | types.rb:9:1:38:3 | C1 | +| types.rb:87:7:87:15 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:87:14:87:15 | 12 | file://:0:0:0:0 | Integer | +| types.rb:88:1:88:16 | self | file://:0:0:0:0 | Object | +| types.rb:88:1:88:16 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:88:7:88:15 | call to new | types.rb:40:1:44:3 | C2 | +| types.rb:88:7:88:15 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:88:14:88:15 | 13 | file://:0:0:0:0 | Integer | +| types.rb:89:1:89:16 | self | file://:0:0:0:0 | Object | +| types.rb:89:1:89:16 | synthetic splat argument | file://:0:0:0:0 | [splat] taint | +| types.rb:89:7:89:15 | call to new | types.rb:46:1:50:3 | C3 | +| types.rb:89:7:89:15 | synthetic splat argument | file://:0:0:0:0 | [splat] new | +| types.rb:89:14:89:15 | 14 | file://:0:0:0:0 | Integer | +#select +| types.rb:42:14:42:17 | self | types.rb:42:14:42:17 | self | types.rb:42:14:42:17 | self | $@ | types.rb:42:14:42:17 | self | self | +| types.rb:42:14:42:17 | self | types.rb:87:7:87:15 | call to new : C1 | types.rb:42:14:42:17 | self | $@ | types.rb:87:7:87:15 | call to new : C1 | call to new : C1 | +| types.rb:42:14:42:17 | self | types.rb:88:7:88:15 | call to new : C2 | types.rb:42:14:42:17 | self | $@ | types.rb:88:7:88:15 | call to new : C2 | call to new : C2 | +| types.rb:48:14:48:17 | self | types.rb:48:14:48:17 | self | types.rb:48:14:48:17 | self | $@ | types.rb:48:14:48:17 | self | self | +| types.rb:48:14:48:17 | self | types.rb:87:7:87:15 | call to new : C1 | types.rb:48:14:48:17 | self | $@ | types.rb:87:7:87:15 | call to new : C1 | call to new : C1 | +| types.rb:48:14:48:17 | self | types.rb:89:7:89:15 | call to new : C3 | types.rb:48:14:48:17 | self | $@ | types.rb:89:7:89:15 | call to new : C3 | call to new : C3 | +| types.rb:55:18:55:18 | x | types.rb:21:13:21:16 | self : C1 | types.rb:55:18:55:18 | x | $@ | types.rb:21:13:21:16 | self : C1 | self : C1 | +| types.rb:55:18:55:18 | x | types.rb:71:11:71:18 | call to new : C1 | types.rb:55:18:55:18 | x | $@ | types.rb:71:11:71:18 | call to new : C1 | call to new : C1 | +| types.rb:55:18:55:18 | x | types.rb:73:11:73:18 | call to new : C3 | types.rb:55:18:55:18 | x | $@ | types.rb:73:11:73:18 | call to new : C3 | call to new : C3 | +| types.rb:55:18:55:18 | x | types.rb:75:7:75:14 | call to new : C1 | types.rb:55:18:55:18 | x | $@ | types.rb:75:7:75:14 | call to new : C1 | call to new : C1 | +| types.rb:55:18:55:18 | x | types.rb:77:7:77:14 | call to new : C3 | types.rb:55:18:55:18 | x | $@ | types.rb:77:7:77:14 | call to new : C3 | call to new : C3 | +| types.rb:64:18:64:19 | c3 | types.rb:25:13:25:16 | self : C1 | types.rb:64:18:64:19 | c3 | $@ | types.rb:25:13:25:16 | self : C1 | self : C1 | +| types.rb:64:18:64:19 | c3 | types.rb:79:11:79:18 | call to new : C1 | types.rb:64:18:64:19 | c3 | $@ | types.rb:79:11:79:18 | call to new : C1 | call to new : C1 | +| types.rb:64:18:64:19 | c3 | types.rb:81:11:81:18 | call to new : C3 | types.rb:64:18:64:19 | c3 | $@ | types.rb:81:11:81:18 | call to new : C3 | call to new : C3 | +| types.rb:64:18:64:19 | c3 | types.rb:83:7:83:14 | call to new : C1 | types.rb:64:18:64:19 | c3 | $@ | types.rb:83:7:83:14 | call to new : C1 | call to new : C1 | +| types.rb:64:18:64:19 | c3 | types.rb:85:7:85:15 | call to new : C3 | types.rb:64:18:64:19 | c3 | $@ | types.rb:85:7:85:15 | call to new : C3 | call to new : C3 | diff --git a/ruby/ql/test/library-tests/dataflow/type-flow/Flow.ql b/ruby/ql/test/library-tests/dataflow/type-flow/Flow.ql new file mode 100644 index 000000000000..f14bb0b7ecc7 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/type-flow/Flow.ql @@ -0,0 +1,54 @@ +/** + * @kind path-problem + */ + +import codeql.ruby.AST +import codeql.ruby.DataFlow +private import TestUtilities.InlineFlowTest +private import codeql.ruby.dataflow.internal.DataFlowPrivate +private import codeql.ruby.dataflow.internal.DataFlowDispatch + +query predicate nodeType(DataFlow::Node node, DataFlowType tp) { + tp = getNodeType(node) and + not tp.isUnknown() +} + +private predicate isSource(DataFlow::Node source, string s) { + exists(MethodCall taint, MethodCall new | + taint.getMethodName() = "taint" and + new.getMethodName() = "new" and + source.asExpr().getExpr() = new and + new = taint.getAnArgument() and + s = new.getAnArgument().getConstantValue().toString() + ) + or + exists(SelfVariableAccess self, Module m | + self = source.asExpr().getExpr() and + not self.isSynthesized() and + selfInMethod(self.getVariable(), _, m) and + s = "self(" + m.getQualifiedName() + ")" + ) +} + +private module FlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { isSource(source, _) } + + predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc | mc.getMethodName() = "sink" | + sink.asExpr().getExpr() = mc.getAnArgument() + ) + } +} + +bindingset[src, sink] +pragma[inline_late] +string getArgString(DataFlow::Node src, DataFlow::Node sink) { + isSource(src, result) and exists(sink) +} + +import ValueFlowTestArgString +import PathGraph + +from PathNode source, PathNode sink +where flowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/ruby/ql/test/library-tests/dataflow/type-flow/types.rb b/ruby/ql/test/library-tests/dataflow/type-flow/types.rb new file mode 100644 index 000000000000..cf4d5bfb78be --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/type-flow/types.rb @@ -0,0 +1,89 @@ +def taint x + x +end + +def sink x + puts "SINK: #{x.get_field}" +end + +class C1 + @field + + def initialize(x) + @field = x + end + + def get_field + @field + end + + def call_foo + foo(self) + end + + def call_bar + bar(self) + end + + def maybe_sink + end + + def call_maybe_sink + maybe_sink + end + + def call_call_maybe_sink + call_maybe_sink + end +end + +class C2 < C1 + def maybe_sink + sink self # $ hasValueFlow=13 $ hasValueFlow=self(C2) $ SPURIOUS: hasValueFlow=12 + end +end + +class C3 < C1 + def maybe_sink + sink self # $ hasValueFlow=14 $ hasValueFlow=self(C3) $ SPURIOUS: hasValueFlow=12 + end +end + +def foo x + case x + when C3 then + sink(x) # $ hasValueFlow=2 $ hasValueFlow=5 $ hasValueFlow=self(C1) $ SPURIOUS: hasValueFlow=0 $ SPURIOUS: hasValueFlow=3 + case x when C2 then sink(x) # dead code + end + end +end + +def bar x + case x + in C3 => c3 then + sink(c3) # $ hasValueFlow=8 $ hasValueFlow=11 $ hasValueFlow=self(C1) $ SPURIOUS: hasValueFlow=6 $ SPURIOUS: hasValueFlow=9 + case c3 when C2 then sink(c3) # dead code + end + else return + end +end + +foo(taint(C1.new 0)) +foo(taint(C2.new 1)) +foo(taint(C3.new 2)) + +taint(C1.new 3).call_foo +taint(C2.new 4).call_foo +taint(C3.new 5).call_foo + +bar(taint(C1.new 6)) +bar(taint(C2.new 7)) +bar(taint(C3.new 8)) + +taint(C1.new 9).call_bar +taint(C2.new 10).call_bar +taint(C3.new 11).call_bar + +taint(C1.new 12).call_call_maybe_sink +taint(C2.new 13).call_call_maybe_sink +taint(C3.new 14).call_call_maybe_sink diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected index a0349ec9ee33..d8d9119f4a1d 100644 --- a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected @@ -5,36 +5,36 @@ testFailures | filter_flow.rb:71:10:71:17 | call to bar | Unexpected result: hasTaintFlow= | | filter_flow.rb:87:11:87:14 | @foo | Unexpected result: hasTaintFlow= | edges -| filter_flow.rb:14:5:14:8 | [post] self [@foo] | filter_flow.rb:17:3:18:5 | self in b [@foo] | +| filter_flow.rb:14:5:14:8 | [post] self [@foo] | filter_flow.rb:17:3:18:5 | self in b : OneController [@foo] | | filter_flow.rb:14:12:14:17 | call to params | filter_flow.rb:14:12:14:23 | ...[...] | | filter_flow.rb:14:12:14:23 | ...[...] | filter_flow.rb:14:5:14:8 | [post] self [@foo] | -| filter_flow.rb:17:3:18:5 | self in b [@foo] | filter_flow.rb:20:3:22:5 | self in c [@foo] | -| filter_flow.rb:20:3:22:5 | self in c [@foo] | filter_flow.rb:21:10:21:13 | self [@foo] | -| filter_flow.rb:21:10:21:13 | self [@foo] | filter_flow.rb:21:10:21:13 | @foo | -| filter_flow.rb:30:5:30:8 | [post] self [@foo] | filter_flow.rb:33:3:35:5 | self in b [@foo] | +| filter_flow.rb:17:3:18:5 | self in b : OneController [@foo] | filter_flow.rb:20:3:22:5 | self in c : OneController [@foo] | +| filter_flow.rb:20:3:22:5 | self in c : OneController [@foo] | filter_flow.rb:21:10:21:13 | self : OneController [@foo] | +| filter_flow.rb:21:10:21:13 | self : OneController [@foo] | filter_flow.rb:21:10:21:13 | @foo | +| filter_flow.rb:30:5:30:8 | [post] self [@foo] | filter_flow.rb:33:3:35:5 | self in b : TwoController [@foo] | | filter_flow.rb:30:12:30:17 | call to params | filter_flow.rb:30:12:30:23 | ...[...] | | filter_flow.rb:30:12:30:23 | ...[...] | filter_flow.rb:30:5:30:8 | [post] self [@foo] | -| filter_flow.rb:33:3:35:5 | self in b [@foo] | filter_flow.rb:37:3:39:5 | self in c [@foo] | -| filter_flow.rb:37:3:39:5 | self in c [@foo] | filter_flow.rb:38:10:38:13 | self [@foo] | -| filter_flow.rb:38:10:38:13 | self [@foo] | filter_flow.rb:38:10:38:13 | @foo | -| filter_flow.rb:47:5:47:8 | [post] self [@foo] | filter_flow.rb:51:3:52:5 | self in b [@foo] | +| filter_flow.rb:33:3:35:5 | self in b : TwoController [@foo] | filter_flow.rb:37:3:39:5 | self in c : TwoController [@foo] | +| filter_flow.rb:37:3:39:5 | self in c : TwoController [@foo] | filter_flow.rb:38:10:38:13 | self : TwoController [@foo] | +| filter_flow.rb:38:10:38:13 | self : TwoController [@foo] | filter_flow.rb:38:10:38:13 | @foo | +| filter_flow.rb:47:5:47:8 | [post] self [@foo] | filter_flow.rb:51:3:52:5 | self in b : ThreeController [@foo] | | filter_flow.rb:47:12:47:17 | call to params | filter_flow.rb:47:12:47:23 | ...[...] | | filter_flow.rb:47:12:47:23 | ...[...] | filter_flow.rb:47:5:47:8 | [post] self [@foo] | -| filter_flow.rb:51:3:52:5 | self in b [@foo] | filter_flow.rb:54:3:56:5 | self in c [@foo] | -| filter_flow.rb:54:3:56:5 | self in c [@foo] | filter_flow.rb:55:10:55:13 | self [@foo] | -| filter_flow.rb:55:10:55:13 | self [@foo] | filter_flow.rb:55:10:55:13 | @foo | -| filter_flow.rb:64:5:64:8 | [post] @foo [@bar] | filter_flow.rb:64:5:64:8 | [post] self [@foo, @bar] | -| filter_flow.rb:64:5:64:8 | [post] self [@foo, @bar] | filter_flow.rb:67:3:68:5 | self in b [@foo, @bar] | +| filter_flow.rb:51:3:52:5 | self in b : ThreeController [@foo] | filter_flow.rb:54:3:56:5 | self in c : ThreeController [@foo] | +| filter_flow.rb:54:3:56:5 | self in c : ThreeController [@foo] | filter_flow.rb:55:10:55:13 | self : ThreeController [@foo] | +| filter_flow.rb:55:10:55:13 | self : ThreeController [@foo] | filter_flow.rb:55:10:55:13 | @foo | +| filter_flow.rb:64:5:64:8 | [post] @foo [@bar] | filter_flow.rb:64:5:64:8 | [post] self : FourController [@foo, @bar] | +| filter_flow.rb:64:5:64:8 | [post] self : FourController [@foo, @bar] | filter_flow.rb:67:3:68:5 | self in b : FourController [@foo, @bar] | | filter_flow.rb:64:16:64:21 | call to params | filter_flow.rb:64:16:64:27 | ...[...] | | filter_flow.rb:64:16:64:27 | ...[...] | filter_flow.rb:64:5:64:8 | [post] @foo [@bar] | -| filter_flow.rb:67:3:68:5 | self in b [@foo, @bar] | filter_flow.rb:70:3:72:5 | self in c [@foo, @bar] | -| filter_flow.rb:70:3:72:5 | self in c [@foo, @bar] | filter_flow.rb:71:10:71:13 | self [@foo, @bar] | +| filter_flow.rb:67:3:68:5 | self in b : FourController [@foo, @bar] | filter_flow.rb:70:3:72:5 | self in c : FourController [@foo, @bar] | +| filter_flow.rb:70:3:72:5 | self in c : FourController [@foo, @bar] | filter_flow.rb:71:10:71:13 | self : FourController [@foo, @bar] | | filter_flow.rb:71:10:71:13 | @foo [@bar] | filter_flow.rb:71:10:71:17 | call to bar | -| filter_flow.rb:71:10:71:13 | self [@foo, @bar] | filter_flow.rb:71:10:71:13 | @foo [@bar] | -| filter_flow.rb:80:5:80:8 | [post] self [@foo] | filter_flow.rb:83:3:84:5 | self in b [@foo] | -| filter_flow.rb:83:3:84:5 | self in b [@foo] | filter_flow.rb:86:3:88:5 | self in c [@foo] | -| filter_flow.rb:86:3:88:5 | self in c [@foo] | filter_flow.rb:87:11:87:14 | self [@foo] | -| filter_flow.rb:87:11:87:14 | self [@foo] | filter_flow.rb:87:11:87:14 | @foo | +| filter_flow.rb:71:10:71:13 | self : FourController [@foo, @bar] | filter_flow.rb:71:10:71:13 | @foo [@bar] | +| filter_flow.rb:80:5:80:8 | [post] self [@foo] | filter_flow.rb:83:3:84:5 | self in b : FiveController [@foo] | +| filter_flow.rb:83:3:84:5 | self in b : FiveController [@foo] | filter_flow.rb:86:3:88:5 | self in c : FiveController [@foo] | +| filter_flow.rb:86:3:88:5 | self in c : FiveController [@foo] | filter_flow.rb:87:11:87:14 | self : FiveController [@foo] | +| filter_flow.rb:87:11:87:14 | self : FiveController [@foo] | filter_flow.rb:87:11:87:14 | @foo | | filter_flow.rb:91:5:91:8 | [post] self [@foo] | filter_flow.rb:80:5:80:8 | [post] self [@foo] | | filter_flow.rb:91:12:91:17 | call to params | filter_flow.rb:91:12:91:23 | ...[...] | | filter_flow.rb:91:12:91:23 | ...[...] | filter_flow.rb:91:5:91:8 | [post] self [@foo] | @@ -47,12 +47,24 @@ edges | params_flow.rb:31:10:31:15 | call to params | params_flow.rb:31:10:31:45 | call to deep_transform_keys | | params_flow.rb:35:10:35:15 | call to params | params_flow.rb:35:10:35:46 | call to deep_transform_keys! | | params_flow.rb:39:10:39:15 | call to params | params_flow.rb:39:10:39:48 | call to delete_if | +| params_flow.rb:39:10:39:15 | call to params | params_flow.rb:39:10:39:48 | call to delete_if [element] | +| params_flow.rb:39:10:39:48 | call to delete_if [element] | params_flow.rb:39:10:39:48 | call to delete_if | | params_flow.rb:43:10:43:15 | call to params | params_flow.rb:43:10:43:32 | call to extract! | | params_flow.rb:47:10:47:15 | call to params | params_flow.rb:47:10:47:46 | call to keep_if | +| params_flow.rb:47:10:47:15 | call to params | params_flow.rb:47:10:47:46 | call to keep_if [element] | +| params_flow.rb:47:10:47:46 | call to keep_if [element] | params_flow.rb:47:10:47:46 | call to keep_if | | params_flow.rb:51:10:51:15 | call to params | params_flow.rb:51:10:51:45 | call to select | +| params_flow.rb:51:10:51:15 | call to params | params_flow.rb:51:10:51:45 | call to select [element] | +| params_flow.rb:51:10:51:45 | call to select [element] | params_flow.rb:51:10:51:45 | call to select | | params_flow.rb:55:10:55:15 | call to params | params_flow.rb:55:10:55:46 | call to select! | +| params_flow.rb:55:10:55:15 | call to params | params_flow.rb:55:10:55:46 | call to select! [element] | +| params_flow.rb:55:10:55:46 | call to select! [element] | params_flow.rb:55:10:55:46 | call to select! | | params_flow.rb:59:10:59:15 | call to params | params_flow.rb:59:10:59:45 | call to reject | +| params_flow.rb:59:10:59:15 | call to params | params_flow.rb:59:10:59:45 | call to reject [element] | +| params_flow.rb:59:10:59:45 | call to reject [element] | params_flow.rb:59:10:59:45 | call to reject | | params_flow.rb:63:10:63:15 | call to params | params_flow.rb:63:10:63:46 | call to reject! | +| params_flow.rb:63:10:63:15 | call to params | params_flow.rb:63:10:63:46 | call to reject! [element] | +| params_flow.rb:63:10:63:46 | call to reject! [element] | params_flow.rb:63:10:63:46 | call to reject! | | params_flow.rb:67:10:67:15 | call to params | params_flow.rb:67:10:67:20 | call to to_h | | params_flow.rb:71:10:71:15 | call to params | params_flow.rb:71:10:71:23 | call to to_hash | | params_flow.rb:75:10:75:15 | call to params | params_flow.rb:75:10:75:24 | call to to_query | @@ -105,38 +117,38 @@ nodes | filter_flow.rb:14:5:14:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | | filter_flow.rb:14:12:14:17 | call to params | semmle.label | call to params | | filter_flow.rb:14:12:14:23 | ...[...] | semmle.label | ...[...] | -| filter_flow.rb:17:3:18:5 | self in b [@foo] | semmle.label | self in b [@foo] | -| filter_flow.rb:20:3:22:5 | self in c [@foo] | semmle.label | self in c [@foo] | +| filter_flow.rb:17:3:18:5 | self in b : OneController [@foo] | semmle.label | self in b : OneController [@foo] | +| filter_flow.rb:20:3:22:5 | self in c : OneController [@foo] | semmle.label | self in c : OneController [@foo] | | filter_flow.rb:21:10:21:13 | @foo | semmle.label | @foo | -| filter_flow.rb:21:10:21:13 | self [@foo] | semmle.label | self [@foo] | +| filter_flow.rb:21:10:21:13 | self : OneController [@foo] | semmle.label | self : OneController [@foo] | | filter_flow.rb:30:5:30:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | | filter_flow.rb:30:12:30:17 | call to params | semmle.label | call to params | | filter_flow.rb:30:12:30:23 | ...[...] | semmle.label | ...[...] | -| filter_flow.rb:33:3:35:5 | self in b [@foo] | semmle.label | self in b [@foo] | -| filter_flow.rb:37:3:39:5 | self in c [@foo] | semmle.label | self in c [@foo] | +| filter_flow.rb:33:3:35:5 | self in b : TwoController [@foo] | semmle.label | self in b : TwoController [@foo] | +| filter_flow.rb:37:3:39:5 | self in c : TwoController [@foo] | semmle.label | self in c : TwoController [@foo] | | filter_flow.rb:38:10:38:13 | @foo | semmle.label | @foo | -| filter_flow.rb:38:10:38:13 | self [@foo] | semmle.label | self [@foo] | +| filter_flow.rb:38:10:38:13 | self : TwoController [@foo] | semmle.label | self : TwoController [@foo] | | filter_flow.rb:47:5:47:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | | filter_flow.rb:47:12:47:17 | call to params | semmle.label | call to params | | filter_flow.rb:47:12:47:23 | ...[...] | semmle.label | ...[...] | -| filter_flow.rb:51:3:52:5 | self in b [@foo] | semmle.label | self in b [@foo] | -| filter_flow.rb:54:3:56:5 | self in c [@foo] | semmle.label | self in c [@foo] | +| filter_flow.rb:51:3:52:5 | self in b : ThreeController [@foo] | semmle.label | self in b : ThreeController [@foo] | +| filter_flow.rb:54:3:56:5 | self in c : ThreeController [@foo] | semmle.label | self in c : ThreeController [@foo] | | filter_flow.rb:55:10:55:13 | @foo | semmle.label | @foo | -| filter_flow.rb:55:10:55:13 | self [@foo] | semmle.label | self [@foo] | +| filter_flow.rb:55:10:55:13 | self : ThreeController [@foo] | semmle.label | self : ThreeController [@foo] | | filter_flow.rb:64:5:64:8 | [post] @foo [@bar] | semmle.label | [post] @foo [@bar] | -| filter_flow.rb:64:5:64:8 | [post] self [@foo, @bar] | semmle.label | [post] self [@foo, @bar] | +| filter_flow.rb:64:5:64:8 | [post] self : FourController [@foo, @bar] | semmle.label | [post] self : FourController [@foo, @bar] | | filter_flow.rb:64:16:64:21 | call to params | semmle.label | call to params | | filter_flow.rb:64:16:64:27 | ...[...] | semmle.label | ...[...] | -| filter_flow.rb:67:3:68:5 | self in b [@foo, @bar] | semmle.label | self in b [@foo, @bar] | -| filter_flow.rb:70:3:72:5 | self in c [@foo, @bar] | semmle.label | self in c [@foo, @bar] | +| filter_flow.rb:67:3:68:5 | self in b : FourController [@foo, @bar] | semmle.label | self in b : FourController [@foo, @bar] | +| filter_flow.rb:70:3:72:5 | self in c : FourController [@foo, @bar] | semmle.label | self in c : FourController [@foo, @bar] | | filter_flow.rb:71:10:71:13 | @foo [@bar] | semmle.label | @foo [@bar] | -| filter_flow.rb:71:10:71:13 | self [@foo, @bar] | semmle.label | self [@foo, @bar] | +| filter_flow.rb:71:10:71:13 | self : FourController [@foo, @bar] | semmle.label | self : FourController [@foo, @bar] | | filter_flow.rb:71:10:71:17 | call to bar | semmle.label | call to bar | | filter_flow.rb:80:5:80:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | -| filter_flow.rb:83:3:84:5 | self in b [@foo] | semmle.label | self in b [@foo] | -| filter_flow.rb:86:3:88:5 | self in c [@foo] | semmle.label | self in c [@foo] | +| filter_flow.rb:83:3:84:5 | self in b : FiveController [@foo] | semmle.label | self in b : FiveController [@foo] | +| filter_flow.rb:86:3:88:5 | self in c : FiveController [@foo] | semmle.label | self in c : FiveController [@foo] | | filter_flow.rb:87:11:87:14 | @foo | semmle.label | @foo | -| filter_flow.rb:87:11:87:14 | self [@foo] | semmle.label | self [@foo] | +| filter_flow.rb:87:11:87:14 | self : FiveController [@foo] | semmle.label | self : FiveController [@foo] | | filter_flow.rb:91:5:91:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | | filter_flow.rb:91:12:91:17 | call to params | semmle.label | call to params | | filter_flow.rb:91:12:91:23 | ...[...] | semmle.label | ...[...] | @@ -158,18 +170,24 @@ nodes | params_flow.rb:35:10:35:46 | call to deep_transform_keys! | semmle.label | call to deep_transform_keys! | | params_flow.rb:39:10:39:15 | call to params | semmle.label | call to params | | params_flow.rb:39:10:39:48 | call to delete_if | semmle.label | call to delete_if | +| params_flow.rb:39:10:39:48 | call to delete_if [element] | semmle.label | call to delete_if [element] | | params_flow.rb:43:10:43:15 | call to params | semmle.label | call to params | | params_flow.rb:43:10:43:32 | call to extract! | semmle.label | call to extract! | | params_flow.rb:47:10:47:15 | call to params | semmle.label | call to params | | params_flow.rb:47:10:47:46 | call to keep_if | semmle.label | call to keep_if | +| params_flow.rb:47:10:47:46 | call to keep_if [element] | semmle.label | call to keep_if [element] | | params_flow.rb:51:10:51:15 | call to params | semmle.label | call to params | | params_flow.rb:51:10:51:45 | call to select | semmle.label | call to select | +| params_flow.rb:51:10:51:45 | call to select [element] | semmle.label | call to select [element] | | params_flow.rb:55:10:55:15 | call to params | semmle.label | call to params | | params_flow.rb:55:10:55:46 | call to select! | semmle.label | call to select! | +| params_flow.rb:55:10:55:46 | call to select! [element] | semmle.label | call to select! [element] | | params_flow.rb:59:10:59:15 | call to params | semmle.label | call to params | | params_flow.rb:59:10:59:45 | call to reject | semmle.label | call to reject | +| params_flow.rb:59:10:59:45 | call to reject [element] | semmle.label | call to reject [element] | | params_flow.rb:63:10:63:15 | call to params | semmle.label | call to params | | params_flow.rb:63:10:63:46 | call to reject! | semmle.label | call to reject! | +| params_flow.rb:63:10:63:46 | call to reject! [element] | semmle.label | call to reject! [element] | | params_flow.rb:67:10:67:15 | call to params | semmle.label | call to params | | params_flow.rb:67:10:67:20 | call to to_h | semmle.label | call to to_h | | params_flow.rb:71:10:71:15 | call to params | semmle.label | call to params | diff --git a/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected b/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected index c5639c0245ca..443b47f989e4 100644 --- a/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected +++ b/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected @@ -57,7 +57,6 @@ 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 | [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] | @@ -134,7 +133,6 @@ 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 | [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] | diff --git a/ruby/ql/test/library-tests/frameworks/sinatra/Sinatra.expected b/ruby/ql/test/library-tests/frameworks/sinatra/Sinatra.expected index 33495e743fd1..5a11ba0690a5 100644 --- a/ruby/ql/test/library-tests/frameworks/sinatra/Sinatra.expected +++ b/ruby/ql/test/library-tests/frameworks/sinatra/Sinatra.expected @@ -43,43 +43,27 @@ filterPatterns | app.rb:106:3:108:5 | call to before | app.rb:106:10:106:23 | "/protected/*" | | app.rb:111:3:113:5 | call to after | app.rb:111:9:111:23 | "/create/:slug" | additionalFlowSteps -| app.rb:84:10:87:5 | [post] do ... end | app.rb:2:22:4:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:6:24:8:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:10:21:13:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:15:23:18:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:20:23:22:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:24:26:26:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:28:26:31:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:33:25:35:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:37:16:42:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:44:53:46:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:48:14:50:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:52:37:54:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:56:32:58:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:60:48:62:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:66:41:68:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:70:20:72:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:74:11:77:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:79:11:82:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:89:16:92:5 | lambda self in do ... end | -| app.rb:84:10:87:5 | [post] do ... end | app.rb:94:15:96:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:2:22:4:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:6:24:8:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:10:21:13:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:15:23:18:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:20:23:22:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:24:26:26:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:28:26:31:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:33:25:35:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:37:16:42:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:44:53:46:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:48:14:50:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:52:37:54:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:56:32:58:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:60:48:62:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:66:41:68:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:70:20:72:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:74:11:77:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:79:11:82:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:89:16:92:5 | lambda self in do ... end | -| app.rb:102:10:104:5 | [post] do ... end | app.rb:94:15:96:5 | lambda self in do ... end | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:3:14:3:19 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:12:5:12:10 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:17:5:17:10 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:25:15:25:20 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:39:13:39:18 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:45:38:45:43 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:57:5:57:15 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:61:5:61:17 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:75:5:75:8 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:81:5:81:12 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:90:5:90:9 | this | +| app.rb:84:10:87:5 | [post] do ... end | app.rb:95:5:95:14 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:3:14:3:19 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:12:5:12:10 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:17:5:17:10 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:25:15:25:20 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:39:13:39:18 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:45:38:45:43 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:57:5:57:15 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:61:5:61:17 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:75:5:75:8 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:81:5:81:12 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:90:5:90:9 | this | +| app.rb:102:10:104:5 | [post] do ... end | app.rb:95:5:95:14 | this | diff --git a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected index 103dc82bda4f..60397ccb22e1 100644 --- a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected +++ b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected @@ -9,13 +9,13 @@ edges | ErbInjection.rb:11:11:11:14 | name | ErbInjection.rb:8:16:11:14 | ... % ... | | SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:11:11:11:14 | name | | SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | -| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | +| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] : String | | SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:5:12:5:24 | ...[...] | | SlimInjection.rb:5:12:5:24 | ...[...] | SlimInjection.rb:5:5:5:8 | name | | SlimInjection.rb:8:16:11:14 | ... % ... | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | | SlimInjection.rb:11:11:11:14 | name | SlimInjection.rb:8:16:11:14 | ... % ... | | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | SlimInjection.rb:14:25:14:32 | bad_text | -| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | SlimInjection.rb:23:25:23:33 | bad2_text | +| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] : String | SlimInjection.rb:23:25:23:33 | bad2_text | nodes | ErbInjection.rb:5:5:5:8 | name | semmle.label | name | | ErbInjection.rb:5:12:5:17 | call to params | semmle.label | call to params | @@ -32,7 +32,7 @@ nodes | SlimInjection.rb:11:11:11:14 | name | semmle.label | name | | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | semmle.label | { ... } [captured bad_text] | | SlimInjection.rb:14:25:14:32 | bad_text | semmle.label | bad_text | -| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | semmle.label | { ... } [captured bad2_text] | +| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] : String | semmle.label | { ... } [captured bad2_text] : String | | SlimInjection.rb:23:25:23:33 | bad2_text | semmle.label | bad2_text | subpaths #select diff --git a/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected b/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected index a93fdd9f008d..417a1950ee75 100644 --- a/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected @@ -20,8 +20,8 @@ edges | tainted_path.rb:10:12:10:43 | call to absolute_path | tainted_path.rb:10:5:10:8 | path | | tainted_path.rb:10:31:10:36 | call to params | tainted_path.rb:10:31:10:43 | ...[...] | | tainted_path.rb:10:31:10:43 | ...[...] | tainted_path.rb:10:12:10:43 | call to absolute_path | -| tainted_path.rb:16:5:16:8 | path | tainted_path.rb:17:26:17:29 | path | -| tainted_path.rb:16:15:16:41 | call to dirname | tainted_path.rb:16:5:16:8 | path | +| tainted_path.rb:16:5:16:8 | path : String | tainted_path.rb:17:26:17:29 | path | +| tainted_path.rb:16:15:16:41 | call to dirname | tainted_path.rb:16:5:16:8 | path : String | | tainted_path.rb:16:28:16:33 | call to params | tainted_path.rb:16:28:16:40 | ...[...] | | tainted_path.rb:16:28:16:40 | ...[...] | tainted_path.rb:16:15:16:41 | call to dirname | | tainted_path.rb:22:5:22:8 | path | tainted_path.rb:23:26:23:29 | path | @@ -93,7 +93,7 @@ nodes | tainted_path.rb:10:31:10:36 | call to params | semmle.label | call to params | | tainted_path.rb:10:31:10:43 | ...[...] | semmle.label | ...[...] | | tainted_path.rb:11:26:11:29 | path | semmle.label | path | -| tainted_path.rb:16:5:16:8 | path | semmle.label | path | +| tainted_path.rb:16:5:16:8 | path : String | semmle.label | path : String | | tainted_path.rb:16:15:16:41 | call to dirname | semmle.label | call to dirname | | tainted_path.rb:16:28:16:33 | call to params | semmle.label | call to params | | tainted_path.rb:16:28:16:40 | ...[...] | semmle.label | ...[...] | diff --git a/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected b/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected index 266da5b21fed..4c59ca30f6d6 100644 --- a/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected @@ -8,12 +8,12 @@ edges | ActiveRecordInjection.rb:43:29:43:39 | ...[...] | ActiveRecordInjection.rb:43:20:43:42 | "id = '#{...}'" | | ActiveRecordInjection.rb:48:30:48:35 | call to params | ActiveRecordInjection.rb:48:30:48:40 | ...[...] | | ActiveRecordInjection.rb:48:30:48:40 | ...[...] | ActiveRecordInjection.rb:48:21:48:43 | "id = '#{...}'" | -| ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" | ActiveRecordInjection.rb:52:21:52:45 | call to [] | +| ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" : String | ActiveRecordInjection.rb:52:21:52:45 | call to [] | | ActiveRecordInjection.rb:52:31:52:36 | call to params | ActiveRecordInjection.rb:52:31:52:41 | ...[...] | -| ActiveRecordInjection.rb:52:31:52:41 | ...[...] | ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" | -| ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" | ActiveRecordInjection.rb:57:22:57:46 | call to [] | +| ActiveRecordInjection.rb:52:31:52:41 | ...[...] | ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" : String | +| ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" : String | ActiveRecordInjection.rb:57:22:57:46 | call to [] | | ActiveRecordInjection.rb:57:32:57:37 | call to params | ActiveRecordInjection.rb:57:32:57:42 | ...[...] | -| ActiveRecordInjection.rb:57:32:57:42 | ...[...] | ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" | +| ActiveRecordInjection.rb:57:32:57:42 | ...[...] | ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" : String | | ActiveRecordInjection.rb:62:21:62:26 | call to params | ActiveRecordInjection.rb:62:21:62:35 | ...[...] | | ActiveRecordInjection.rb:62:21:62:35 | ...[...] | ActiveRecordInjection.rb:61:16:61:21 | <<-SQL | | ActiveRecordInjection.rb:68:34:68:39 | call to params | ActiveRecordInjection.rb:68:34:68:44 | ...[...] | @@ -37,13 +37,10 @@ edges | ActiveRecordInjection.rb:108:23:108:28 | call to params | ActiveRecordInjection.rb:108:23:108:47 | ...[...] | | ActiveRecordInjection.rb:114:5:114:6 | ps | ActiveRecordInjection.rb:115:11:115:12 | ps | | ActiveRecordInjection.rb:114:10:114:15 | call to params | ActiveRecordInjection.rb:114:5:114:6 | ps | -| ActiveRecordInjection.rb:115:5:115:7 | uid | ActiveRecordInjection.rb:116:5:116:9 | uidEq | +| ActiveRecordInjection.rb:115:5:115:7 | uid | ActiveRecordInjection.rb:116:5:116:9 | uidEq : String | | ActiveRecordInjection.rb:115:11:115:12 | ps | ActiveRecordInjection.rb:115:11:115:17 | ...[...] | | ActiveRecordInjection.rb:115:11:115:17 | ...[...] | ActiveRecordInjection.rb:115:5:115:7 | uid | -| ActiveRecordInjection.rb:116:5:116:9 | uidEq | ActiveRecordInjection.rb:120:20:120:32 | ... + ... | -| ActiveRecordInjection.rb:116:5:116:9 | uidEq | ActiveRecordInjection.rb:120:28:120:32 | uidEq | -| ActiveRecordInjection.rb:120:20:120:32 | ... + ... [element] | ActiveRecordInjection.rb:120:20:120:32 | ... + ... | -| ActiveRecordInjection.rb:120:28:120:32 | uidEq | ActiveRecordInjection.rb:120:20:120:32 | ... + ... [element] | +| ActiveRecordInjection.rb:116:5:116:9 | uidEq : String | ActiveRecordInjection.rb:120:20:120:32 | ... + ... | | ActiveRecordInjection.rb:153:21:153:26 | call to params | ActiveRecordInjection.rb:153:21:153:44 | ...[...] | | ActiveRecordInjection.rb:153:21:153:26 | call to params | ActiveRecordInjection.rb:153:21:153:44 | ...[...] | | ActiveRecordInjection.rb:153:21:153:44 | ...[...] | ActiveRecordInjection.rb:20:22:20:30 | condition | @@ -51,9 +48,9 @@ edges | ActiveRecordInjection.rb:167:59:167:74 | ...[...] | ActiveRecordInjection.rb:167:27:167:76 | "this is an unsafe annotation:..." | | ActiveRecordInjection.rb:178:5:178:13 | my_params | ActiveRecordInjection.rb:179:47:179:55 | my_params | | ActiveRecordInjection.rb:178:17:178:32 | call to permitted_params | ActiveRecordInjection.rb:178:5:178:13 | my_params | -| ActiveRecordInjection.rb:179:5:179:9 | query | ActiveRecordInjection.rb:180:37:180:41 | query | +| ActiveRecordInjection.rb:179:5:179:9 | query : String | ActiveRecordInjection.rb:180:37:180:41 | query | | ActiveRecordInjection.rb:179:47:179:55 | my_params | ActiveRecordInjection.rb:179:47:179:65 | ...[...] | -| ActiveRecordInjection.rb:179:47:179:65 | ...[...] | ActiveRecordInjection.rb:179:5:179:9 | query | +| ActiveRecordInjection.rb:179:47:179:65 | ...[...] | ActiveRecordInjection.rb:179:5:179:9 | query : String | | ActiveRecordInjection.rb:185:5:185:10 | call to params | ActiveRecordInjection.rb:185:5:185:27 | call to require | | ActiveRecordInjection.rb:185:5:185:27 | call to require | ActiveRecordInjection.rb:185:5:185:59 | call to permit | | ActiveRecordInjection.rb:185:5:185:59 | call to permit | ActiveRecordInjection.rb:178:17:178:32 | call to permitted_params | @@ -66,18 +63,18 @@ edges | ArelInjection.rb:4:5:4:8 | name | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | | ArelInjection.rb:4:12:4:17 | call to params | ArelInjection.rb:4:12:4:29 | ...[...] | | ArelInjection.rb:4:12:4:29 | ...[...] | ArelInjection.rb:4:5:4:8 | name | -| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:13:5:13:8 | qry1 | -| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:19:5:19:8 | qry2 | -| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:31:5:31:8 | qry3 | -| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:43:5:43:8 | qry3 | +| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:13:5:13:8 | qry1 : String | +| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:19:5:19:8 | qry2 : String | +| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:31:5:31:8 | qry3 : String | +| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:43:5:43:8 | qry3 : String | | PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:6:12:6:24 | ...[...] | | PgInjection.rb:6:12:6:24 | ...[...] | PgInjection.rb:6:5:6:8 | name | -| PgInjection.rb:13:5:13:8 | qry1 | PgInjection.rb:14:15:14:18 | qry1 | -| PgInjection.rb:13:5:13:8 | qry1 | PgInjection.rb:15:21:15:24 | qry1 | -| PgInjection.rb:19:5:19:8 | qry2 | PgInjection.rb:20:22:20:25 | qry2 | -| PgInjection.rb:19:5:19:8 | qry2 | PgInjection.rb:21:28:21:31 | qry2 | -| PgInjection.rb:31:5:31:8 | qry3 | PgInjection.rb:32:29:32:32 | qry3 | -| PgInjection.rb:43:5:43:8 | qry3 | PgInjection.rb:44:29:44:32 | qry3 | +| PgInjection.rb:13:5:13:8 | qry1 : String | PgInjection.rb:14:15:14:18 | qry1 | +| PgInjection.rb:13:5:13:8 | qry1 : String | PgInjection.rb:15:21:15:24 | qry1 | +| PgInjection.rb:19:5:19:8 | qry2 : String | PgInjection.rb:20:22:20:25 | qry2 | +| PgInjection.rb:19:5:19:8 | qry2 : String | PgInjection.rb:21:28:21:31 | qry2 | +| PgInjection.rb:31:5:31:8 | qry3 : String | PgInjection.rb:32:29:32:32 | qry3 | +| PgInjection.rb:43:5:43:8 | qry3 : String | PgInjection.rb:44:29:44:32 | qry3 | nodes | ActiveRecordInjection.rb:8:25:8:28 | name | semmle.label | name | | ActiveRecordInjection.rb:8:31:8:34 | pass | semmle.label | pass | @@ -95,11 +92,11 @@ nodes | ActiveRecordInjection.rb:48:30:48:35 | call to params | semmle.label | call to params | | ActiveRecordInjection.rb:48:30:48:40 | ...[...] | semmle.label | ...[...] | | ActiveRecordInjection.rb:52:21:52:45 | call to [] | semmle.label | call to [] | -| ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" | semmle.label | "id = '#{...}'" | +| ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" : String | semmle.label | "id = '#{...}'" : String | | ActiveRecordInjection.rb:52:31:52:36 | call to params | semmle.label | call to params | | ActiveRecordInjection.rb:52:31:52:41 | ...[...] | semmle.label | ...[...] | | ActiveRecordInjection.rb:57:22:57:46 | call to [] | semmle.label | call to [] | -| ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" | semmle.label | "id = '#{...}'" | +| ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" : String | semmle.label | "id = '#{...}'" : String | | ActiveRecordInjection.rb:57:32:57:37 | call to params | semmle.label | call to params | | ActiveRecordInjection.rb:57:32:57:42 | ...[...] | semmle.label | ...[...] | | ActiveRecordInjection.rb:61:16:61:21 | <<-SQL | semmle.label | <<-SQL | @@ -140,10 +137,8 @@ nodes | ActiveRecordInjection.rb:115:5:115:7 | uid | semmle.label | uid | | ActiveRecordInjection.rb:115:11:115:12 | ps | semmle.label | ps | | ActiveRecordInjection.rb:115:11:115:17 | ...[...] | semmle.label | ...[...] | -| ActiveRecordInjection.rb:116:5:116:9 | uidEq | semmle.label | uidEq | +| ActiveRecordInjection.rb:116:5:116:9 | uidEq : String | semmle.label | uidEq : String | | ActiveRecordInjection.rb:120:20:120:32 | ... + ... | semmle.label | ... + ... | -| ActiveRecordInjection.rb:120:20:120:32 | ... + ... [element] | semmle.label | ... + ... [element] | -| ActiveRecordInjection.rb:120:28:120:32 | uidEq | semmle.label | uidEq | | ActiveRecordInjection.rb:153:21:153:26 | call to params | semmle.label | call to params | | ActiveRecordInjection.rb:153:21:153:44 | ...[...] | semmle.label | ...[...] | | ActiveRecordInjection.rb:153:21:153:44 | ...[...] | semmle.label | ...[...] | @@ -152,7 +147,7 @@ nodes | ActiveRecordInjection.rb:167:59:167:74 | ...[...] | semmle.label | ...[...] | | ActiveRecordInjection.rb:178:5:178:13 | my_params | semmle.label | my_params | | ActiveRecordInjection.rb:178:17:178:32 | call to permitted_params | semmle.label | call to permitted_params | -| ActiveRecordInjection.rb:179:5:179:9 | query | semmle.label | query | +| ActiveRecordInjection.rb:179:5:179:9 | query : String | semmle.label | query : String | | ActiveRecordInjection.rb:179:47:179:55 | my_params | semmle.label | my_params | | ActiveRecordInjection.rb:179:47:179:65 | ...[...] | semmle.label | ...[...] | | ActiveRecordInjection.rb:180:37:180:41 | query | semmle.label | query | @@ -172,15 +167,15 @@ nodes | PgInjection.rb:6:5:6:8 | name | semmle.label | name | | PgInjection.rb:6:12:6:17 | call to params | semmle.label | call to params | | PgInjection.rb:6:12:6:24 | ...[...] | semmle.label | ...[...] | -| PgInjection.rb:13:5:13:8 | qry1 | semmle.label | qry1 | +| PgInjection.rb:13:5:13:8 | qry1 : String | semmle.label | qry1 : String | | PgInjection.rb:14:15:14:18 | qry1 | semmle.label | qry1 | | PgInjection.rb:15:21:15:24 | qry1 | semmle.label | qry1 | -| PgInjection.rb:19:5:19:8 | qry2 | semmle.label | qry2 | +| PgInjection.rb:19:5:19:8 | qry2 : String | semmle.label | qry2 : String | | PgInjection.rb:20:22:20:25 | qry2 | semmle.label | qry2 | | PgInjection.rb:21:28:21:31 | qry2 | semmle.label | qry2 | -| PgInjection.rb:31:5:31:8 | qry3 | semmle.label | qry3 | +| PgInjection.rb:31:5:31:8 | qry3 : String | semmle.label | qry3 : String | | PgInjection.rb:32:29:32:32 | qry3 | semmle.label | qry3 | -| PgInjection.rb:43:5:43:8 | qry3 | semmle.label | qry3 | +| PgInjection.rb:43:5:43:8 | qry3 : String | semmle.label | qry3 : String | | PgInjection.rb:44:29:44:32 | qry3 | semmle.label | qry3 | subpaths #select diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected index 8b9e7e3abed0..eee2f1fbbb4e 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected @@ -31,20 +31,20 @@ edges | CodeInjection.rb:86:10:86:25 | ... + ... [element] | CodeInjection.rb:86:10:86:37 | ... + ... [element] | | CodeInjection.rb:86:10:86:37 | ... + ... [element] | CodeInjection.rb:86:10:86:37 | ... + ... | | CodeInjection.rb:86:22:86:25 | code | CodeInjection.rb:86:10:86:25 | ... + ... [element] | -| CodeInjection.rb:101:3:102:5 | self in index [@foo] | CodeInjection.rb:111:3:113:5 | self in baz [@foo] | -| CodeInjection.rb:101:3:102:5 | self in index [@foo] | CodeInjection.rb:111:3:113:5 | self in baz [@foo] | -| CodeInjection.rb:105:5:105:8 | [post] self [@foo] | CodeInjection.rb:108:3:109:5 | self in bar [@foo] | -| CodeInjection.rb:105:5:105:8 | [post] self [@foo] | CodeInjection.rb:108:3:109:5 | self in bar [@foo] | +| CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | +| CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | +| CodeInjection.rb:105:5:105:8 | [post] self [@foo] | CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | +| CodeInjection.rb:105:5:105:8 | [post] self [@foo] | CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | | CodeInjection.rb:105:12:105:17 | call to params | CodeInjection.rb:105:12:105:23 | ...[...] | | CodeInjection.rb:105:12:105:17 | call to params | CodeInjection.rb:105:12:105:23 | ...[...] | | CodeInjection.rb:105:12:105:23 | ...[...] | CodeInjection.rb:105:5:105:8 | [post] self [@foo] | | CodeInjection.rb:105:12:105:23 | ...[...] | CodeInjection.rb:105:5:105:8 | [post] self [@foo] | -| CodeInjection.rb:108:3:109:5 | self in bar [@foo] | CodeInjection.rb:101:3:102:5 | self in index [@foo] | -| CodeInjection.rb:108:3:109:5 | self in bar [@foo] | CodeInjection.rb:101:3:102:5 | self in index [@foo] | -| CodeInjection.rb:111:3:113:5 | self in baz [@foo] | CodeInjection.rb:112:10:112:13 | self [@foo] | -| CodeInjection.rb:111:3:113:5 | self in baz [@foo] | CodeInjection.rb:112:10:112:13 | self [@foo] | -| CodeInjection.rb:112:10:112:13 | self [@foo] | CodeInjection.rb:112:10:112:13 | @foo | -| CodeInjection.rb:112:10:112:13 | self [@foo] | CodeInjection.rb:112:10:112:13 | @foo | +| CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | +| CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | +| CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | +| CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | +| CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | CodeInjection.rb:112:10:112:13 | @foo | +| CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | CodeInjection.rb:112:10:112:13 | @foo | nodes | CodeInjection.rb:5:5:5:8 | code | semmle.label | code | | CodeInjection.rb:5:5:5:8 | code | semmle.label | code | @@ -82,22 +82,22 @@ nodes | CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | semmle.label | "prefix_#{...}_suffix" | | CodeInjection.rb:90:10:90:13 | code | semmle.label | code | | CodeInjection.rb:90:10:90:13 | code | semmle.label | code | -| CodeInjection.rb:101:3:102:5 | self in index [@foo] | semmle.label | self in index [@foo] | -| CodeInjection.rb:101:3:102:5 | self in index [@foo] | semmle.label | self in index [@foo] | +| CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | semmle.label | self in index : PostsController [@foo] | +| CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | semmle.label | self in index : PostsController [@foo] | | CodeInjection.rb:105:5:105:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | | CodeInjection.rb:105:5:105:8 | [post] self [@foo] | semmle.label | [post] self [@foo] | | CodeInjection.rb:105:12:105:17 | call to params | semmle.label | call to params | | CodeInjection.rb:105:12:105:17 | call to params | semmle.label | call to params | | CodeInjection.rb:105:12:105:23 | ...[...] | semmle.label | ...[...] | | CodeInjection.rb:105:12:105:23 | ...[...] | semmle.label | ...[...] | -| CodeInjection.rb:108:3:109:5 | self in bar [@foo] | semmle.label | self in bar [@foo] | -| CodeInjection.rb:108:3:109:5 | self in bar [@foo] | semmle.label | self in bar [@foo] | -| CodeInjection.rb:111:3:113:5 | self in baz [@foo] | semmle.label | self in baz [@foo] | -| CodeInjection.rb:111:3:113:5 | self in baz [@foo] | semmle.label | self in baz [@foo] | +| CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | semmle.label | self in bar : PostsController [@foo] | +| CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | semmle.label | self in bar : PostsController [@foo] | +| CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | semmle.label | self in baz : PostsController [@foo] | +| CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | semmle.label | self in baz : PostsController [@foo] | | CodeInjection.rb:112:10:112:13 | @foo | semmle.label | @foo | | CodeInjection.rb:112:10:112:13 | @foo | semmle.label | @foo | -| CodeInjection.rb:112:10:112:13 | self [@foo] | semmle.label | self [@foo] | -| CodeInjection.rb:112:10:112:13 | self [@foo] | semmle.label | self [@foo] | +| CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | semmle.label | self : PostsController [@foo] | +| CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | semmle.label | self : PostsController [@foo] | subpaths #select | CodeInjection.rb:8:10:8:13 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:8:10:8:13 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected b/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected index a35aef729365..b3e8a7c7441e 100644 --- a/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected +++ b/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected @@ -1,46 +1,46 @@ edges -| logging.rb:3:1:3:8 | password | logging.rb:6:20:6:27 | password | -| logging.rb:3:1:3:8 | password | logging.rb:8:21:8:28 | password | -| logging.rb:3:1:3:8 | password | logging.rb:10:21:10:28 | password | -| logging.rb:3:1:3:8 | password | logging.rb:12:21:12:28 | password | -| logging.rb:3:1:3:8 | password | logging.rb:14:23:14:30 | password | -| logging.rb:3:1:3:8 | password | logging.rb:16:20:16:27 | password | -| logging.rb:3:1:3:8 | password | logging.rb:19:33:19:40 | password | -| logging.rb:3:1:3:8 | password | logging.rb:21:44:21:51 | password | -| logging.rb:3:1:3:8 | password | logging.rb:23:33:23:40 | password | -| logging.rb:3:1:3:8 | password | logging.rb:26:18:26:34 | "pw: #{...}" | -| logging.rb:3:1:3:8 | password | logging.rb:28:26:28:33 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:3:1:3:8 | password | -| logging.rb:30:1:30:4 | hsh1 [element :password] | logging.rb:38:20:38:23 | hsh1 [element :password] | -| logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" | logging.rb:30:1:30:4 | hsh1 [element :password] | -| logging.rb:34:1:34:4 | [post] hsh2 [element :password] | logging.rb:35:1:35:4 | hsh3 [element :password] | -| logging.rb:34:1:34:4 | [post] hsh2 [element :password] | logging.rb:40:20:40:23 | hsh2 [element :password] | -| logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | logging.rb:34:1:34:4 | [post] hsh2 [element :password] | -| logging.rb:35:1:35:4 | hsh3 [element :password] | logging.rb:42:20:42:23 | hsh3 [element :password] | -| logging.rb:38:20:38:23 | hsh1 [element :password] | logging.rb:38:20:38:34 | ...[...] | -| logging.rb:40:20:40:23 | hsh2 [element :password] | logging.rb:40:20:40:34 | ...[...] | -| logging.rb:42:20:42:23 | hsh3 [element :password] | logging.rb:42:20:42:34 | ...[...] | -| logging.rb:64:1:64:31 | password_masked_ineffective_sub | logging.rb:68:35:68:65 | password_masked_ineffective_sub | -| logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" | logging.rb:64:1:64:31 | password_masked_ineffective_sub | -| logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex | logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | -| logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" | logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex | -| logging.rb:66:1:66:32 | password_masked_ineffective_gsub | logging.rb:70:36:70:67 | password_masked_ineffective_gsub | -| logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" | logging.rb:66:1:66:32 | password_masked_ineffective_gsub | -| logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | -| logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" | logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex | +| logging.rb:3:1:3:8 | password : String | logging.rb:6:20:6:27 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:8:21:8:28 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:10:21:10:28 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:12:21:12:28 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:14:23:14:30 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:16:20:16:27 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:19:33:19:40 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:21:44:21:51 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:23:33:23:40 | password | +| logging.rb:3:1:3:8 | password : String | logging.rb:26:18:26:34 | "pw: #{...}" | +| logging.rb:3:1:3:8 | password : String | logging.rb:28:26:28:33 | password | +| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:3:1:3:8 | password : String | +| logging.rb:30:1:30:4 | hsh1 [element :password] : String | logging.rb:38:20:38:23 | hsh1 [element :password] : String | +| logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" : String | logging.rb:30:1:30:4 | hsh1 [element :password] : String | +| logging.rb:34:1:34:4 | [post] hsh2 [element :password] : String | logging.rb:35:1:35:4 | hsh3 [element :password] : String | +| logging.rb:34:1:34:4 | [post] hsh2 [element :password] : String | logging.rb:40:20:40:23 | hsh2 [element :password] : String | +| logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" : String | logging.rb:34:1:34:4 | [post] hsh2 [element :password] : String | +| logging.rb:35:1:35:4 | hsh3 [element :password] : String | logging.rb:42:20:42:23 | hsh3 [element :password] : String | +| logging.rb:38:20:38:23 | hsh1 [element :password] : String | logging.rb:38:20:38:34 | ...[...] | +| logging.rb:40:20:40:23 | hsh2 [element :password] : String | logging.rb:40:20:40:34 | ...[...] | +| logging.rb:42:20:42:23 | hsh3 [element :password] : String | logging.rb:42:20:42:34 | ...[...] | +| logging.rb:64:1:64:31 | password_masked_ineffective_sub : String | logging.rb:68:35:68:65 | password_masked_ineffective_sub : String | +| logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" : String | logging.rb:64:1:64:31 | password_masked_ineffective_sub : String | +| logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex : String | logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | +| logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" : String | logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex : String | +| logging.rb:66:1:66:32 | password_masked_ineffective_gsub : String | logging.rb:70:36:70:67 | password_masked_ineffective_gsub : String | +| logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" : String | logging.rb:66:1:66:32 | password_masked_ineffective_gsub : String | +| logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex : String | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | +| logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" : String | logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex : String | | logging.rb:68:1:68:31 | password_masked_ineffective_sub | logging.rb:74:20:74:50 | password_masked_ineffective_sub | -| logging.rb:68:35:68:65 | password_masked_ineffective_sub | logging.rb:68:35:68:88 | call to sub | +| logging.rb:68:35:68:65 | password_masked_ineffective_sub : String | logging.rb:68:35:68:88 | call to sub | | logging.rb:68:35:68:88 | call to sub | logging.rb:68:1:68:31 | password_masked_ineffective_sub | | logging.rb:70:1:70:32 | password_masked_ineffective_gsub | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | -| logging.rb:70:36:70:67 | password_masked_ineffective_gsub | logging.rb:70:36:70:86 | call to gsub | +| logging.rb:70:36:70:67 | password_masked_ineffective_gsub : String | logging.rb:70:36:70:86 | call to gsub | | logging.rb:70:36:70:86 | call to gsub | logging.rb:70:1:70:32 | password_masked_ineffective_gsub | -| logging.rb:82:9:82:16 | password | logging.rb:84:15:84:22 | password | -| logging.rb:87:1:87:12 | password_arg | logging.rb:88:5:88:16 | password_arg | -| logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" | logging.rb:87:1:87:12 | password_arg | -| logging.rb:88:5:88:16 | password_arg | logging.rb:82:9:82:16 | password | +| logging.rb:82:9:82:16 | password : String | logging.rb:84:15:84:22 | password | +| logging.rb:87:1:87:12 | password_arg : String | logging.rb:88:5:88:16 | password_arg : String | +| logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" : String | logging.rb:87:1:87:12 | password_arg : String | +| logging.rb:88:5:88:16 | password_arg : String | logging.rb:82:9:82:16 | password : String | nodes -| logging.rb:3:1:3:8 | password | semmle.label | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | semmle.label | "043697b96909e03ca907599d6420555f" | +| logging.rb:3:1:3:8 | password : String | semmle.label | password : String | +| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | semmle.label | "043697b96909e03ca907599d6420555f" : String | | logging.rb:6:20:6:27 | password | semmle.label | password | | logging.rb:8:21:8:28 | password | semmle.label | password | | logging.rb:10:21:10:28 | password | semmle.label | password | @@ -52,61 +52,61 @@ nodes | logging.rb:23:33:23:40 | password | semmle.label | password | | logging.rb:26:18:26:34 | "pw: #{...}" | semmle.label | "pw: #{...}" | | logging.rb:28:26:28:33 | password | semmle.label | password | -| logging.rb:30:1:30:4 | hsh1 [element :password] | semmle.label | hsh1 [element :password] | -| logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" | semmle.label | "aec5058e61f7f122998b1a30ee2c66b6" | -| logging.rb:34:1:34:4 | [post] hsh2 [element :password] | semmle.label | [post] hsh2 [element :password] | -| logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | semmle.label | "beeda625d7306b45784d91ea0336e201" | -| logging.rb:35:1:35:4 | hsh3 [element :password] | semmle.label | hsh3 [element :password] | -| logging.rb:38:20:38:23 | hsh1 [element :password] | semmle.label | hsh1 [element :password] | +| logging.rb:30:1:30:4 | hsh1 [element :password] : String | semmle.label | hsh1 [element :password] : String | +| logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" : String | semmle.label | "aec5058e61f7f122998b1a30ee2c66b6" : String | +| logging.rb:34:1:34:4 | [post] hsh2 [element :password] : String | semmle.label | [post] hsh2 [element :password] : String | +| logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" : String | semmle.label | "beeda625d7306b45784d91ea0336e201" : String | +| logging.rb:35:1:35:4 | hsh3 [element :password] : String | semmle.label | hsh3 [element :password] : String | +| logging.rb:38:20:38:23 | hsh1 [element :password] : String | semmle.label | hsh1 [element :password] : String | | logging.rb:38:20:38:34 | ...[...] | semmle.label | ...[...] | -| logging.rb:40:20:40:23 | hsh2 [element :password] | semmle.label | hsh2 [element :password] | +| logging.rb:40:20:40:23 | hsh2 [element :password] : String | semmle.label | hsh2 [element :password] : String | | logging.rb:40:20:40:34 | ...[...] | semmle.label | ...[...] | -| logging.rb:42:20:42:23 | hsh3 [element :password] | semmle.label | hsh3 [element :password] | +| logging.rb:42:20:42:23 | hsh3 [element :password] : String | semmle.label | hsh3 [element :password] : String | | logging.rb:42:20:42:34 | ...[...] | semmle.label | ...[...] | -| logging.rb:64:1:64:31 | password_masked_ineffective_sub | semmle.label | password_masked_ineffective_sub | -| logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" | semmle.label | "ca497451f5e883662fb1a37bc9ec7838" | -| logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex | semmle.label | password_masked_ineffective_sub_ex | -| logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" | semmle.label | "ca497451f5e883662fb1a37bc9ec7838" | -| logging.rb:66:1:66:32 | password_masked_ineffective_gsub | semmle.label | password_masked_ineffective_gsub | -| logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" | semmle.label | "a7e3747b19930d4f4b8181047194832f" | -| logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex | semmle.label | password_masked_ineffective_gsub_ex | -| logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" | semmle.label | "a7e3747b19930d4f4b8181047194832f" | +| logging.rb:64:1:64:31 | password_masked_ineffective_sub : String | semmle.label | password_masked_ineffective_sub : String | +| logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" : String | semmle.label | "ca497451f5e883662fb1a37bc9ec7838" : String | +| logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex : String | semmle.label | password_masked_ineffective_sub_ex : String | +| logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" : String | semmle.label | "ca497451f5e883662fb1a37bc9ec7838" : String | +| logging.rb:66:1:66:32 | password_masked_ineffective_gsub : String | semmle.label | password_masked_ineffective_gsub : String | +| logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" : String | semmle.label | "a7e3747b19930d4f4b8181047194832f" : String | +| logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex : String | semmle.label | password_masked_ineffective_gsub_ex : String | +| logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" : String | semmle.label | "a7e3747b19930d4f4b8181047194832f" : String | | logging.rb:68:1:68:31 | password_masked_ineffective_sub | semmle.label | password_masked_ineffective_sub | -| logging.rb:68:35:68:65 | password_masked_ineffective_sub | semmle.label | password_masked_ineffective_sub | +| logging.rb:68:35:68:65 | password_masked_ineffective_sub : String | semmle.label | password_masked_ineffective_sub : String | | logging.rb:68:35:68:88 | call to sub | semmle.label | call to sub | | logging.rb:70:1:70:32 | password_masked_ineffective_gsub | semmle.label | password_masked_ineffective_gsub | -| logging.rb:70:36:70:67 | password_masked_ineffective_gsub | semmle.label | password_masked_ineffective_gsub | +| logging.rb:70:36:70:67 | password_masked_ineffective_gsub : String | semmle.label | password_masked_ineffective_gsub : String | | logging.rb:70:36:70:86 | call to gsub | semmle.label | call to gsub | | logging.rb:74:20:74:50 | password_masked_ineffective_sub | semmle.label | password_masked_ineffective_sub | | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | semmle.label | password_masked_ineffective_gsub | | logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | semmle.label | password_masked_ineffective_sub_ex | | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | semmle.label | password_masked_ineffective_gsub_ex | -| logging.rb:82:9:82:16 | password | semmle.label | password | +| logging.rb:82:9:82:16 | password : String | semmle.label | password : String | | logging.rb:84:15:84:22 | password | semmle.label | password | -| logging.rb:87:1:87:12 | password_arg | semmle.label | password_arg | -| logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" | semmle.label | "65f2950df2f0e2c38d7ba2ccca767291" | -| logging.rb:88:5:88:16 | password_arg | semmle.label | password_arg | +| logging.rb:87:1:87:12 | password_arg : String | semmle.label | password_arg : String | +| logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" : String | semmle.label | "65f2950df2f0e2c38d7ba2ccca767291" : String | +| logging.rb:88:5:88:16 | password_arg : String | semmle.label | password_arg : String | subpaths #select -| logging.rb:6:20:6:27 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:6:20:6:27 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:8:21:8:28 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:8:21:8:28 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:10:21:10:28 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:10:21:10:28 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:12:21:12:28 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:12:21:12:28 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:14:23:14:30 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:14:23:14:30 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:16:20:16:27 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:16:20:16:27 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:19:33:19:40 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:19:33:19:40 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:21:44:21:51 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:21:44:21:51 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:23:33:23:40 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:23:33:23:40 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:26:18:26:34 | "pw: #{...}" | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:26:18:26:34 | "pw: #{...}" | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:28:26:28:33 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:28:26:28:33 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | -| logging.rb:38:20:38:34 | ...[...] | logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" | logging.rb:38:20:38:34 | ...[...] | This logs sensitive data returned by $@ as clear text. | logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" | a write to password | -| logging.rb:40:20:40:34 | ...[...] | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | logging.rb:40:20:40:34 | ...[...] | This logs sensitive data returned by $@ as clear text. | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | a write to password | -| logging.rb:42:20:42:34 | ...[...] | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | logging.rb:42:20:42:34 | ...[...] | This logs sensitive data returned by $@ as clear text. | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | a write to password | -| logging.rb:74:20:74:50 | password_masked_ineffective_sub | logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" | logging.rb:74:20:74:50 | password_masked_ineffective_sub | This logs sensitive data returned by $@ as clear text. | logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" | an assignment to password_masked_ineffective_sub | +| logging.rb:6:20:6:27 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:6:20:6:27 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:8:21:8:28 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:8:21:8:28 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:10:21:10:28 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:10:21:10:28 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:12:21:12:28 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:12:21:12:28 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:14:23:14:30 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:14:23:14:30 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:16:20:16:27 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:16:20:16:27 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:19:33:19:40 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:19:33:19:40 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:21:44:21:51 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:21:44:21:51 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:23:33:23:40 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:23:33:23:40 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:26:18:26:34 | "pw: #{...}" | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:26:18:26:34 | "pw: #{...}" | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:28:26:28:33 | password | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : String | logging.rb:28:26:28:33 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | an assignment to password | +| logging.rb:38:20:38:34 | ...[...] | logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" : String | logging.rb:38:20:38:34 | ...[...] | This logs sensitive data returned by $@ as clear text. | logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" | a write to password | +| logging.rb:40:20:40:34 | ...[...] | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" : String | logging.rb:40:20:40:34 | ...[...] | This logs sensitive data returned by $@ as clear text. | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | a write to password | +| logging.rb:42:20:42:34 | ...[...] | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" : String | logging.rb:42:20:42:34 | ...[...] | This logs sensitive data returned by $@ as clear text. | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" | a write to password | +| logging.rb:74:20:74:50 | password_masked_ineffective_sub | logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" : String | logging.rb:74:20:74:50 | password_masked_ineffective_sub | This logs sensitive data returned by $@ as clear text. | logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" | an assignment to password_masked_ineffective_sub | | logging.rb:74:20:74:50 | password_masked_ineffective_sub | logging.rb:68:35:68:88 | call to sub | logging.rb:74:20:74:50 | password_masked_ineffective_sub | This logs sensitive data returned by $@ as clear text. | logging.rb:68:35:68:88 | call to sub | an assignment to password_masked_ineffective_sub | -| logging.rb:76:20:76:51 | password_masked_ineffective_gsub | logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | This logs sensitive data returned by $@ as clear text. | logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" | an assignment to password_masked_ineffective_gsub | +| logging.rb:76:20:76:51 | password_masked_ineffective_gsub | logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" : String | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | This logs sensitive data returned by $@ as clear text. | logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" | an assignment to password_masked_ineffective_gsub | | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | logging.rb:70:36:70:86 | call to gsub | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | This logs sensitive data returned by $@ as clear text. | logging.rb:70:36:70:86 | call to gsub | an assignment to password_masked_ineffective_gsub | -| logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" | logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | This logs sensitive data returned by $@ as clear text. | logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" | an assignment to password_masked_ineffective_sub_ex | -| logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | This logs sensitive data returned by $@ as clear text. | logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" | an assignment to password_masked_ineffective_gsub_ex | +| logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" : String | logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | This logs sensitive data returned by $@ as clear text. | logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" | an assignment to password_masked_ineffective_sub_ex | +| logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" : String | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | This logs sensitive data returned by $@ as clear text. | logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" | an assignment to password_masked_ineffective_gsub_ex | | logging.rb:84:15:84:22 | password | logging.rb:84:15:84:22 | password | logging.rb:84:15:84:22 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:84:15:84:22 | password | a parameter password | -| logging.rb:84:15:84:22 | password | logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" | logging.rb:84:15:84:22 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" | an assignment to password_arg | +| logging.rb:84:15:84:22 | password | logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" : String | logging.rb:84:15:84:22 | password | This logs sensitive data returned by $@ as clear text. | logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" | an assignment to password_arg | diff --git a/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected b/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected index 9ec7e50e4600..5d12d7947155 100644 --- a/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected +++ b/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected @@ -1,96 +1,100 @@ edges -| app/controllers/users_controller.rb:3:5:3:16 | new_password | app/controllers/users_controller.rb:5:39:5:50 | new_password | -| app/controllers/users_controller.rb:3:5:3:16 | new_password | app/controllers/users_controller.rb:7:41:7:52 | new_password | -| app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | app/controllers/users_controller.rb:3:5:3:16 | new_password | -| app/controllers/users_controller.rb:11:5:11:16 | new_password | app/controllers/users_controller.rb:13:42:13:53 | new_password | -| app/controllers/users_controller.rb:11:5:11:16 | new_password | app/controllers/users_controller.rb:15:49:15:60 | new_password | -| app/controllers/users_controller.rb:11:5:11:16 | new_password | app/controllers/users_controller.rb:15:49:15:60 | new_password | -| app/controllers/users_controller.rb:11:5:11:16 | new_password | app/controllers/users_controller.rb:15:87:15:98 | new_password | -| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | app/controllers/users_controller.rb:11:5:11:16 | new_password | +| app/controllers/users_controller.rb:3:5:3:16 | new_password : String | app/controllers/users_controller.rb:5:39:5:50 | new_password | +| app/controllers/users_controller.rb:3:5:3:16 | new_password : String | app/controllers/users_controller.rb:7:41:7:52 | new_password | +| app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : String | app/controllers/users_controller.rb:3:5:3:16 | new_password : String | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : String | app/controllers/users_controller.rb:13:42:13:53 | new_password | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : String | app/controllers/users_controller.rb:15:49:15:60 | new_password | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : String | app/controllers/users_controller.rb:15:49:15:60 | new_password : String | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : String | app/controllers/users_controller.rb:15:87:15:98 | new_password | +| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : String | app/controllers/users_controller.rb:11:5:11:16 | new_password : String | | app/controllers/users_controller.rb:15:49:15:60 | new_password | app/controllers/users_controller.rb:15:87:15:98 | new_password | -| app/controllers/users_controller.rb:19:5:19:16 | new_password | app/controllers/users_controller.rb:21:45:21:56 | new_password | -| app/controllers/users_controller.rb:19:5:19:16 | new_password | app/controllers/users_controller.rb:21:45:21:56 | new_password | -| app/controllers/users_controller.rb:19:5:19:16 | new_password | app/controllers/users_controller.rb:21:83:21:94 | new_password | -| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | app/controllers/users_controller.rb:19:5:19:16 | new_password | +| app/controllers/users_controller.rb:15:49:15:60 | new_password : String | app/controllers/users_controller.rb:15:87:15:98 | new_password | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : String | app/controllers/users_controller.rb:21:45:21:56 | new_password | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : String | app/controllers/users_controller.rb:21:45:21:56 | new_password : String | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : String | app/controllers/users_controller.rb:21:83:21:94 | new_password | +| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : String | app/controllers/users_controller.rb:19:5:19:16 | new_password : String | | app/controllers/users_controller.rb:21:45:21:56 | new_password | app/controllers/users_controller.rb:21:83:21:94 | new_password | -| app/controllers/users_controller.rb:26:5:26:16 | new_password | app/controllers/users_controller.rb:28:27:28:38 | new_password | -| app/controllers/users_controller.rb:26:5:26:16 | new_password | app/controllers/users_controller.rb:30:28:30:39 | new_password | -| app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | app/controllers/users_controller.rb:26:5:26:16 | new_password | -| app/controllers/users_controller.rb:35:5:35:16 | new_password | app/controllers/users_controller.rb:37:39:37:50 | new_password | -| app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" | app/controllers/users_controller.rb:35:5:35:16 | new_password | -| app/controllers/users_controller.rb:42:5:42:16 | new_password | app/controllers/users_controller.rb:44:21:44:32 | new_password | -| app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" | app/controllers/users_controller.rb:42:5:42:16 | new_password | -| app/controllers/users_controller.rb:58:5:58:16 | new_password | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | -| app/controllers/users_controller.rb:58:5:58:16 | new_password | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | -| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | app/controllers/users_controller.rb:58:5:58:16 | new_password | -| app/models/user.rb:3:5:3:16 | new_password | app/models/user.rb:5:27:5:38 | new_password | -| app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" | app/models/user.rb:3:5:3:16 | new_password | -| app/models/user.rb:9:5:9:16 | new_password | app/models/user.rb:11:22:11:33 | new_password | -| app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" | app/models/user.rb:9:5:9:16 | new_password | -| app/models/user.rb:15:5:15:16 | new_password | app/models/user.rb:17:21:17:32 | new_password | -| app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" | app/models/user.rb:15:5:15:16 | new_password | +| app/controllers/users_controller.rb:21:45:21:56 | new_password : String | app/controllers/users_controller.rb:21:83:21:94 | new_password | +| app/controllers/users_controller.rb:26:5:26:16 | new_password : String | app/controllers/users_controller.rb:28:27:28:38 | new_password | +| app/controllers/users_controller.rb:26:5:26:16 | new_password : String | app/controllers/users_controller.rb:30:28:30:39 | new_password | +| app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : String | app/controllers/users_controller.rb:26:5:26:16 | new_password : String | +| app/controllers/users_controller.rb:35:5:35:16 | new_password : String | app/controllers/users_controller.rb:37:39:37:50 | new_password | +| app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" : String | app/controllers/users_controller.rb:35:5:35:16 | new_password : String | +| app/controllers/users_controller.rb:42:5:42:16 | new_password : String | app/controllers/users_controller.rb:44:21:44:32 | new_password | +| app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" : String | app/controllers/users_controller.rb:42:5:42:16 | new_password : String | +| app/controllers/users_controller.rb:58:5:58:16 | new_password : String | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | +| app/controllers/users_controller.rb:58:5:58:16 | new_password : String | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | +| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : String | app/controllers/users_controller.rb:58:5:58:16 | new_password : String | +| app/models/user.rb:3:5:3:16 | new_password : String | app/models/user.rb:5:27:5:38 | new_password | +| app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" : String | app/models/user.rb:3:5:3:16 | new_password : String | +| app/models/user.rb:9:5:9:16 | new_password : String | app/models/user.rb:11:22:11:33 | new_password | +| app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" : String | app/models/user.rb:9:5:9:16 | new_password : String | +| app/models/user.rb:15:5:15:16 | new_password : String | app/models/user.rb:17:21:17:32 | new_password | +| app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" : String | app/models/user.rb:15:5:15:16 | new_password : String | nodes -| app/controllers/users_controller.rb:3:5:3:16 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | semmle.label | "043697b96909e03ca907599d6420555f" | +| app/controllers/users_controller.rb:3:5:3:16 | new_password : String | semmle.label | new_password : String | +| app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : String | semmle.label | "043697b96909e03ca907599d6420555f" : String | | app/controllers/users_controller.rb:5:39:5:50 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:7:41:7:52 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:11:5:11:16 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | semmle.label | "083c9e1da4cc0c2f5480bb4dbe6ff141" | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : String | semmle.label | new_password : String | +| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : String | semmle.label | "083c9e1da4cc0c2f5480bb4dbe6ff141" : String | | app/controllers/users_controller.rb:13:42:13:53 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:15:49:15:60 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:15:49:15:60 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:15:49:15:60 | new_password : String | semmle.label | new_password : String | | app/controllers/users_controller.rb:15:87:15:98 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:19:5:19:16 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | semmle.label | "504d224a806cf8073cd14ef08242d422" | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : String | semmle.label | new_password : String | +| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : String | semmle.label | "504d224a806cf8073cd14ef08242d422" : String | | app/controllers/users_controller.rb:21:45:21:56 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:21:45:21:56 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:21:45:21:56 | new_password : String | semmle.label | new_password : String | | app/controllers/users_controller.rb:21:83:21:94 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:26:5:26:16 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | semmle.label | "7d6ae08394c3f284506dca70f05995f6" | +| app/controllers/users_controller.rb:26:5:26:16 | new_password : String | semmle.label | new_password : String | +| app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : String | semmle.label | "7d6ae08394c3f284506dca70f05995f6" : String | | app/controllers/users_controller.rb:28:27:28:38 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:30:28:30:39 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:35:5:35:16 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" | semmle.label | "ff295f8648a406c37fbe378377320e4c" | +| app/controllers/users_controller.rb:35:5:35:16 | new_password : String | semmle.label | new_password : String | +| app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" : String | semmle.label | "ff295f8648a406c37fbe378377320e4c" : String | | app/controllers/users_controller.rb:37:39:37:50 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:42:5:42:16 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" | semmle.label | "78ffbec583b546bd073efd898f833184" | +| app/controllers/users_controller.rb:42:5:42:16 | new_password : String | semmle.label | new_password : String | +| app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" : String | semmle.label | "78ffbec583b546bd073efd898f833184" : String | | app/controllers/users_controller.rb:44:21:44:32 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:58:5:58:16 | new_password | semmle.label | new_password | -| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | semmle.label | "0157af7c38cbdd24f1616de4e5321861" | +| app/controllers/users_controller.rb:58:5:58:16 | new_password : String | semmle.label | new_password : String | +| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : String | semmle.label | "0157af7c38cbdd24f1616de4e5321861" : String | | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | semmle.label | "password: #{...}\\n" | | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | semmle.label | "password: #{...}" | -| app/models/user.rb:3:5:3:16 | new_password | semmle.label | new_password | -| app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" | semmle.label | "06c38c6a8a9c11a9d3b209a3193047b4" | +| app/models/user.rb:3:5:3:16 | new_password : String | semmle.label | new_password : String | +| app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" : String | semmle.label | "06c38c6a8a9c11a9d3b209a3193047b4" : String | | app/models/user.rb:5:27:5:38 | new_password | semmle.label | new_password | -| app/models/user.rb:9:5:9:16 | new_password | semmle.label | new_password | -| app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" | semmle.label | "52652fb5c709fb6b9b5a0194af7c6067" | +| app/models/user.rb:9:5:9:16 | new_password : String | semmle.label | new_password : String | +| app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" : String | semmle.label | "52652fb5c709fb6b9b5a0194af7c6067" : String | | app/models/user.rb:11:22:11:33 | new_password | semmle.label | new_password | -| app/models/user.rb:15:5:15:16 | new_password | semmle.label | new_password | -| app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" | semmle.label | "f982bf2531c149a8a1444a951b12e830" | +| app/models/user.rb:15:5:15:16 | new_password : String | semmle.label | new_password : String | +| app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" : String | semmle.label | "f982bf2531c149a8a1444a951b12e830" : String | | app/models/user.rb:17:21:17:32 | new_password | semmle.label | new_password | subpaths #select -| app/controllers/users_controller.rb:5:39:5:50 | new_password | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | app/controllers/users_controller.rb:5:39:5:50 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | an assignment to new_password | -| app/controllers/users_controller.rb:7:41:7:52 | new_password | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | app/controllers/users_controller.rb:7:41:7:52 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | an assignment to new_password | +| app/controllers/users_controller.rb:5:39:5:50 | new_password | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : String | app/controllers/users_controller.rb:5:39:5:50 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | an assignment to new_password | +| app/controllers/users_controller.rb:7:41:7:52 | new_password | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : String | app/controllers/users_controller.rb:7:41:7:52 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" | an assignment to new_password | | app/controllers/users_controller.rb:7:41:7:52 | new_password | app/controllers/users_controller.rb:7:41:7:52 | new_password | app/controllers/users_controller.rb:7:41:7:52 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:7:41:7:52 | new_password | a write to password | -| app/controllers/users_controller.rb:13:42:13:53 | new_password | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | app/controllers/users_controller.rb:13:42:13:53 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | an assignment to new_password | -| app/controllers/users_controller.rb:15:49:15:60 | new_password | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | app/controllers/users_controller.rb:15:49:15:60 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | an assignment to new_password | +| app/controllers/users_controller.rb:13:42:13:53 | new_password | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : String | app/controllers/users_controller.rb:13:42:13:53 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | an assignment to new_password | +| app/controllers/users_controller.rb:15:49:15:60 | new_password | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : String | app/controllers/users_controller.rb:15:49:15:60 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | an assignment to new_password | | app/controllers/users_controller.rb:15:49:15:60 | new_password | app/controllers/users_controller.rb:15:49:15:60 | new_password | app/controllers/users_controller.rb:15:49:15:60 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:15:49:15:60 | new_password | a write to password | -| app/controllers/users_controller.rb:15:87:15:98 | new_password | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | app/controllers/users_controller.rb:15:87:15:98 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | an assignment to new_password | +| app/controllers/users_controller.rb:15:87:15:98 | new_password | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : String | app/controllers/users_controller.rb:15:87:15:98 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" | an assignment to new_password | | app/controllers/users_controller.rb:15:87:15:98 | new_password | app/controllers/users_controller.rb:15:49:15:60 | new_password | app/controllers/users_controller.rb:15:87:15:98 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:15:49:15:60 | new_password | a write to password | | app/controllers/users_controller.rb:15:87:15:98 | new_password | app/controllers/users_controller.rb:15:87:15:98 | new_password | app/controllers/users_controller.rb:15:87:15:98 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:15:87:15:98 | new_password | a write to password | -| app/controllers/users_controller.rb:21:45:21:56 | new_password | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | app/controllers/users_controller.rb:21:45:21:56 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | an assignment to new_password | +| app/controllers/users_controller.rb:21:45:21:56 | new_password | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : String | app/controllers/users_controller.rb:21:45:21:56 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | an assignment to new_password | | app/controllers/users_controller.rb:21:45:21:56 | new_password | app/controllers/users_controller.rb:21:45:21:56 | new_password | app/controllers/users_controller.rb:21:45:21:56 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:21:45:21:56 | new_password | a write to password | -| app/controllers/users_controller.rb:21:83:21:94 | new_password | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | app/controllers/users_controller.rb:21:83:21:94 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | an assignment to new_password | +| app/controllers/users_controller.rb:21:83:21:94 | new_password | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : String | app/controllers/users_controller.rb:21:83:21:94 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" | an assignment to new_password | | app/controllers/users_controller.rb:21:83:21:94 | new_password | app/controllers/users_controller.rb:21:45:21:56 | new_password | app/controllers/users_controller.rb:21:83:21:94 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:21:45:21:56 | new_password | a write to password | | app/controllers/users_controller.rb:21:83:21:94 | new_password | app/controllers/users_controller.rb:21:83:21:94 | new_password | app/controllers/users_controller.rb:21:83:21:94 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:21:83:21:94 | new_password | a write to password | -| app/controllers/users_controller.rb:28:27:28:38 | new_password | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | app/controllers/users_controller.rb:28:27:28:38 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | an assignment to new_password | -| app/controllers/users_controller.rb:30:28:30:39 | new_password | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | app/controllers/users_controller.rb:30:28:30:39 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | an assignment to new_password | +| app/controllers/users_controller.rb:28:27:28:38 | new_password | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : String | app/controllers/users_controller.rb:28:27:28:38 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | an assignment to new_password | +| app/controllers/users_controller.rb:30:28:30:39 | new_password | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : String | app/controllers/users_controller.rb:30:28:30:39 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" | an assignment to new_password | | app/controllers/users_controller.rb:30:28:30:39 | new_password | app/controllers/users_controller.rb:30:28:30:39 | new_password | app/controllers/users_controller.rb:30:28:30:39 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:30:28:30:39 | new_password | a write to password | -| app/controllers/users_controller.rb:37:39:37:50 | new_password | app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" | app/controllers/users_controller.rb:37:39:37:50 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" | an assignment to new_password | -| app/controllers/users_controller.rb:44:21:44:32 | new_password | app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" | app/controllers/users_controller.rb:44:21:44:32 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" | an assignment to new_password | -| app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | an assignment to new_password | -| app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | an assignment to new_password | -| app/models/user.rb:5:27:5:38 | new_password | app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" | app/models/user.rb:5:27:5:38 | new_password | This stores sensitive data returned by $@ as clear text. | app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" | an assignment to new_password | -| app/models/user.rb:11:22:11:33 | new_password | app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" | app/models/user.rb:11:22:11:33 | new_password | This stores sensitive data returned by $@ as clear text. | app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" | an assignment to new_password | -| app/models/user.rb:17:21:17:32 | new_password | app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" | app/models/user.rb:17:21:17:32 | new_password | This stores sensitive data returned by $@ as clear text. | app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" | an assignment to new_password | +| app/controllers/users_controller.rb:37:39:37:50 | new_password | app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" : String | app/controllers/users_controller.rb:37:39:37:50 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" | an assignment to new_password | +| app/controllers/users_controller.rb:44:21:44:32 | new_password | app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" : String | app/controllers/users_controller.rb:44:21:44:32 | new_password | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" | an assignment to new_password | +| app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : String | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | an assignment to new_password | +| app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : String | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | This stores sensitive data returned by $@ as clear text. | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | an assignment to new_password | +| app/models/user.rb:5:27:5:38 | new_password | app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" : String | app/models/user.rb:5:27:5:38 | new_password | This stores sensitive data returned by $@ as clear text. | app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" | an assignment to new_password | +| app/models/user.rb:11:22:11:33 | new_password | app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" : String | app/models/user.rb:11:22:11:33 | new_password | This stores sensitive data returned by $@ as clear text. | app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" | an assignment to new_password | +| app/models/user.rb:17:21:17:32 | new_password | app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" : String | app/models/user.rb:17:21:17:32 | new_password | This stores sensitive data returned by $@ as clear text. | app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" | an assignment to new_password | diff --git a/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected index 57918d9da205..03e43dfc15e8 100644 --- a/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected +++ b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected @@ -1,33 +1,33 @@ edges -| tst.rb:1:7:1:7 | r | tst.rb:2:4:2:4 | r | -| tst.rb:2:4:2:4 | r | tst.rb:2:3:2:15 | call to pack | -| tst.rb:5:1:5:23 | totally_harmless_string | tst.rb:7:8:7:30 | totally_harmless_string | -| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." | tst.rb:5:1:5:23 | totally_harmless_string | -| tst.rb:7:8:7:30 | totally_harmless_string | tst.rb:1:7:1:7 | r | -| tst.rb:7:8:7:30 | totally_harmless_string | tst.rb:7:6:7:31 | call to e | -| tst.rb:10:11:10:24 | "666f6f626172" | tst.rb:1:7:1:7 | r | -| tst.rb:10:11:10:24 | "666f6f626172" | tst.rb:10:9:10:25 | call to e | -| tst.rb:16:1:16:27 | another_questionable_string | tst.rb:17:6:17:32 | another_questionable_string | -| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." | tst.rb:16:1:16:27 | another_questionable_string | -| tst.rb:17:6:17:32 | another_questionable_string | tst.rb:17:6:17:38 | call to strip | +| tst.rb:1:7:1:7 | r : String | tst.rb:2:4:2:4 | r : String | +| tst.rb:2:4:2:4 | r : String | tst.rb:2:3:2:15 | call to pack | +| tst.rb:5:1:5:23 | totally_harmless_string : String | tst.rb:7:8:7:30 | totally_harmless_string : String | +| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : String | tst.rb:5:1:5:23 | totally_harmless_string : String | +| tst.rb:7:8:7:30 | totally_harmless_string : String | tst.rb:1:7:1:7 | r : String | +| tst.rb:7:8:7:30 | totally_harmless_string : String | tst.rb:7:6:7:31 | call to e | +| tst.rb:10:11:10:24 | "666f6f626172" : String | tst.rb:1:7:1:7 | r : String | +| tst.rb:10:11:10:24 | "666f6f626172" : String | tst.rb:10:9:10:25 | call to e | +| tst.rb:16:1:16:27 | another_questionable_string : String | tst.rb:17:6:17:32 | another_questionable_string : String | +| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : String | tst.rb:16:1:16:27 | another_questionable_string : String | +| tst.rb:17:6:17:32 | another_questionable_string : String | tst.rb:17:6:17:38 | call to strip | nodes -| tst.rb:1:7:1:7 | r | semmle.label | r | +| tst.rb:1:7:1:7 | r : String | semmle.label | r : String | | tst.rb:2:3:2:15 | call to pack | semmle.label | call to pack | -| tst.rb:2:4:2:4 | r | semmle.label | r | -| tst.rb:5:1:5:23 | totally_harmless_string | semmle.label | totally_harmless_string | -| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." | semmle.label | "707574732822636f646520696e6a6..." | +| tst.rb:2:4:2:4 | r : String | semmle.label | r : String | +| tst.rb:5:1:5:23 | totally_harmless_string : String | semmle.label | totally_harmless_string : String | +| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : String | semmle.label | "707574732822636f646520696e6a6..." : String | | tst.rb:7:6:7:31 | call to e | semmle.label | call to e | -| tst.rb:7:8:7:30 | totally_harmless_string | semmle.label | totally_harmless_string | +| tst.rb:7:8:7:30 | totally_harmless_string : String | semmle.label | totally_harmless_string : String | | tst.rb:10:9:10:25 | call to e | semmle.label | call to e | -| tst.rb:10:11:10:24 | "666f6f626172" | semmle.label | "666f6f626172" | -| tst.rb:16:1:16:27 | another_questionable_string | semmle.label | another_questionable_string | -| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." | semmle.label | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." | -| tst.rb:17:6:17:32 | another_questionable_string | semmle.label | another_questionable_string | +| tst.rb:10:11:10:24 | "666f6f626172" : String | semmle.label | "666f6f626172" : String | +| tst.rb:16:1:16:27 | another_questionable_string : String | semmle.label | another_questionable_string : String | +| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : String | semmle.label | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : String | +| tst.rb:17:6:17:32 | another_questionable_string : String | semmle.label | another_questionable_string : String | | tst.rb:17:6:17:38 | call to strip | semmle.label | call to strip | subpaths -| tst.rb:7:8:7:30 | totally_harmless_string | tst.rb:1:7:1:7 | r | tst.rb:2:3:2:15 | call to pack | tst.rb:7:6:7:31 | call to e | -| tst.rb:10:11:10:24 | "666f6f626172" | tst.rb:1:7:1:7 | r | tst.rb:2:3:2:15 | call to pack | tst.rb:10:9:10:25 | call to e | +| tst.rb:7:8:7:30 | totally_harmless_string : String | tst.rb:1:7:1:7 | r : String | tst.rb:2:3:2:15 | call to pack | tst.rb:7:6:7:31 | call to e | +| tst.rb:10:11:10:24 | "666f6f626172" : String | tst.rb:1:7:1:7 | r : String | tst.rb:2:3:2:15 | call to pack | tst.rb:10:9:10:25 | call to e | #select -| tst.rb:7:6:7:31 | call to e | tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." | tst.rb:7:6:7:31 | call to e | $@ is interpreted as code. | tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." | Hard-coded data | -| tst.rb:10:9:10:25 | call to e | tst.rb:10:11:10:24 | "666f6f626172" | tst.rb:10:9:10:25 | call to e | $@ is interpreted as an import path. | tst.rb:10:11:10:24 | "666f6f626172" | Hard-coded data | -| tst.rb:17:6:17:38 | call to strip | tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." | tst.rb:17:6:17:38 | call to strip | $@ is interpreted as code. | tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." | Hard-coded data | +| tst.rb:7:6:7:31 | call to e | tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : String | tst.rb:7:6:7:31 | call to e | $@ is interpreted as code. | tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." | Hard-coded data | +| tst.rb:10:9:10:25 | call to e | tst.rb:10:11:10:24 | "666f6f626172" : String | tst.rb:10:9:10:25 | call to e | $@ is interpreted as an import path. | tst.rb:10:11:10:24 | "666f6f626172" | Hard-coded data | +| tst.rb:17:6:17:38 | call to strip | tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : String | tst.rb:17:6:17:38 | call to strip | $@ is interpreted as code. | tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." | Hard-coded data | diff --git a/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected b/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected index a4e8218f8c1d..3d4f4d1f3862 100644 --- a/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected +++ b/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected @@ -1,25 +1,25 @@ edges -| FilePermissions.rb:51:3:51:6 | perm | FilePermissions.rb:53:19:53:22 | perm | -| FilePermissions.rb:51:3:51:6 | perm | FilePermissions.rb:54:3:54:7 | perm2 | -| FilePermissions.rb:51:10:51:13 | 0777 | FilePermissions.rb:51:3:51:6 | perm | -| FilePermissions.rb:54:3:54:7 | perm2 | FilePermissions.rb:56:19:56:23 | perm2 | -| FilePermissions.rb:58:3:58:6 | perm | FilePermissions.rb:59:3:59:7 | perm2 | -| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" | FilePermissions.rb:58:3:58:6 | perm | -| FilePermissions.rb:59:3:59:7 | perm2 | FilePermissions.rb:61:19:61:23 | perm2 | +| FilePermissions.rb:51:3:51:6 | perm : Integer | FilePermissions.rb:53:19:53:22 | perm | +| FilePermissions.rb:51:3:51:6 | perm : Integer | FilePermissions.rb:54:3:54:7 | perm2 : Integer | +| FilePermissions.rb:51:10:51:13 | 0777 : Integer | FilePermissions.rb:51:3:51:6 | perm : Integer | +| FilePermissions.rb:54:3:54:7 | perm2 : Integer | FilePermissions.rb:56:19:56:23 | perm2 | +| FilePermissions.rb:58:3:58:6 | perm : String | FilePermissions.rb:59:3:59:7 | perm2 : String | +| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" : String | FilePermissions.rb:58:3:58:6 | perm : String | +| FilePermissions.rb:59:3:59:7 | perm2 : String | FilePermissions.rb:61:19:61:23 | perm2 | nodes | FilePermissions.rb:5:19:5:22 | 0222 | semmle.label | 0222 | | FilePermissions.rb:7:19:7:22 | 0622 | semmle.label | 0622 | | FilePermissions.rb:9:19:9:22 | 0755 | semmle.label | 0755 | | FilePermissions.rb:11:19:11:22 | 0777 | semmle.label | 0777 | | FilePermissions.rb:28:13:28:16 | 0755 | semmle.label | 0755 | -| FilePermissions.rb:51:3:51:6 | perm | semmle.label | perm | -| FilePermissions.rb:51:10:51:13 | 0777 | semmle.label | 0777 | +| FilePermissions.rb:51:3:51:6 | perm : Integer | semmle.label | perm : Integer | +| FilePermissions.rb:51:10:51:13 | 0777 : Integer | semmle.label | 0777 : Integer | | FilePermissions.rb:53:19:53:22 | perm | semmle.label | perm | -| FilePermissions.rb:54:3:54:7 | perm2 | semmle.label | perm2 | +| FilePermissions.rb:54:3:54:7 | perm2 : Integer | semmle.label | perm2 : Integer | | FilePermissions.rb:56:19:56:23 | perm2 | semmle.label | perm2 | -| FilePermissions.rb:58:3:58:6 | perm | semmle.label | perm | -| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" | semmle.label | "u=wrx,g=rwx,o=x" | -| FilePermissions.rb:59:3:59:7 | perm2 | semmle.label | perm2 | +| FilePermissions.rb:58:3:58:6 | perm : String | semmle.label | perm : String | +| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" : String | semmle.label | "u=wrx,g=rwx,o=x" : String | +| FilePermissions.rb:59:3:59:7 | perm2 : String | semmle.label | perm2 : String | | FilePermissions.rb:61:19:61:23 | perm2 | semmle.label | perm2 | | FilePermissions.rb:63:19:63:29 | "u=rwx,o+r" | semmle.label | "u=rwx,o+r" | | FilePermissions.rb:67:19:67:24 | "a+rw" | semmle.label | "a+rw" | @@ -31,9 +31,9 @@ subpaths | FilePermissions.rb:9:19:9:22 | 0755 | FilePermissions.rb:9:19:9:22 | 0755 | FilePermissions.rb:9:19:9:22 | 0755 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:9:3:9:32 | call to chmod | call to chmod | | FilePermissions.rb:11:19:11:22 | 0777 | FilePermissions.rb:11:19:11:22 | 0777 | FilePermissions.rb:11:19:11:22 | 0777 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:11:3:11:32 | call to chmod | call to chmod | | FilePermissions.rb:28:13:28:16 | 0755 | FilePermissions.rb:28:13:28:16 | 0755 | FilePermissions.rb:28:13:28:16 | 0755 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:28:3:28:26 | call to chmod | call to chmod | -| FilePermissions.rb:51:10:51:13 | 0777 | FilePermissions.rb:51:10:51:13 | 0777 | FilePermissions.rb:53:19:53:22 | perm | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:53:3:53:32 | call to chmod | call to chmod | -| FilePermissions.rb:51:10:51:13 | 0777 | FilePermissions.rb:51:10:51:13 | 0777 | FilePermissions.rb:56:19:56:23 | perm2 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:56:3:56:33 | call to chmod | call to chmod | -| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" | FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" | FilePermissions.rb:61:19:61:23 | perm2 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:61:3:61:33 | call to chmod | call to chmod | +| FilePermissions.rb:51:10:51:13 | 0777 | FilePermissions.rb:51:10:51:13 | 0777 : Integer | FilePermissions.rb:53:19:53:22 | perm | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:53:3:53:32 | call to chmod | call to chmod | +| FilePermissions.rb:51:10:51:13 | 0777 | FilePermissions.rb:51:10:51:13 | 0777 : Integer | FilePermissions.rb:56:19:56:23 | perm2 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:56:3:56:33 | call to chmod | call to chmod | +| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" | FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" : String | FilePermissions.rb:61:19:61:23 | perm2 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:61:3:61:33 | call to chmod | call to chmod | | FilePermissions.rb:63:19:63:29 | "u=rwx,o+r" | FilePermissions.rb:63:19:63:29 | "u=rwx,o+r" | FilePermissions.rb:63:19:63:29 | "u=rwx,o+r" | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:63:3:63:39 | call to chmod | call to chmod | | FilePermissions.rb:67:19:67:24 | "a+rw" | FilePermissions.rb:67:19:67:24 | "a+rw" | FilePermissions.rb:67:19:67:24 | "a+rw" | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:67:3:67:34 | call to chmod | call to chmod | | FilePermissions.rb:72:21:72:24 | 0755 | FilePermissions.rb:72:21:72:24 | 0755 | FilePermissions.rb:72:21:72:24 | 0755 | This overly permissive mask used in $@ allows read or write access to others. | FilePermissions.rb:72:3:72:34 | call to chmod_R | call to chmod_R | diff --git a/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected b/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected index 3492e9b41aec..180f342e49ca 100644 --- a/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected +++ b/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected @@ -1,55 +1,55 @@ edges -| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | HardcodedCredentials.rb:1:23:1:30 | password | -| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:1:33:1:36 | cert | +| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : String | HardcodedCredentials.rb:1:23:1:30 | password | +| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : String | HardcodedCredentials.rb:1:33:1:36 | cert | | HardcodedCredentials.rb:18:19:18:72 | ... + ... | HardcodedCredentials.rb:1:23:1:30 | password | -| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | HardcodedCredentials.rb:18:19:18:72 | ... + ... | -| HardcodedCredentials.rb:20:1:20:7 | pw_left | HardcodedCredentials.rb:22:6:22:12 | pw_left | -| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | HardcodedCredentials.rb:20:1:20:7 | pw_left | -| HardcodedCredentials.rb:21:1:21:8 | pw_right | HardcodedCredentials.rb:22:16:22:23 | pw_right | -| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | HardcodedCredentials.rb:21:1:21:8 | pw_right | +| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : String | HardcodedCredentials.rb:18:19:18:72 | ... + ... | +| HardcodedCredentials.rb:20:1:20:7 | pw_left : String | HardcodedCredentials.rb:22:6:22:12 | pw_left : String | +| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : String | HardcodedCredentials.rb:20:1:20:7 | pw_left : String | +| HardcodedCredentials.rb:21:1:21:8 | pw_right : String | HardcodedCredentials.rb:22:16:22:23 | pw_right : String | +| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" : String | HardcodedCredentials.rb:21:1:21:8 | pw_right : String | | HardcodedCredentials.rb:22:1:22:2 | pw | HardcodedCredentials.rb:23:19:23:20 | pw | -| HardcodedCredentials.rb:22:6:22:12 | pw_left | HardcodedCredentials.rb:22:6:22:23 | ... + ... | +| HardcodedCredentials.rb:22:6:22:12 | pw_left : String | HardcodedCredentials.rb:22:6:22:23 | ... + ... | | HardcodedCredentials.rb:22:6:22:23 | ... + ... | HardcodedCredentials.rb:22:1:22:2 | pw | -| HardcodedCredentials.rb:22:16:22:23 | pw_right | HardcodedCredentials.rb:22:6:22:23 | ... + ... | +| HardcodedCredentials.rb:22:16:22:23 | pw_right : String | HardcodedCredentials.rb:22:6:22:23 | ... + ... | | HardcodedCredentials.rb:23:19:23:20 | pw | HardcodedCredentials.rb:1:23:1:30 | password | -| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | HardcodedCredentials.rb:31:18:31:23 | passwd | -| HardcodedCredentials.rb:43:29:43:43 | "user@test.com" | HardcodedCredentials.rb:43:18:43:25 | username | -| HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" | HardcodedCredentials.rb:43:46:43:53 | password | +| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : String | HardcodedCredentials.rb:31:18:31:23 | passwd | +| HardcodedCredentials.rb:43:29:43:43 | "user@test.com" : String | HardcodedCredentials.rb:43:18:43:25 | username | +| HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" : String | HardcodedCredentials.rb:43:46:43:53 | password | nodes | HardcodedCredentials.rb:1:23:1:30 | password | semmle.label | password | | HardcodedCredentials.rb:1:33:1:36 | cert | semmle.label | cert | | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | semmle.label | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | semmle.label | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | -| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | semmle.label | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | -| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | semmle.label | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | +| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : String | semmle.label | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : String | | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | semmle.label | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | +| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : String | semmle.label | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : String | | HardcodedCredentials.rb:18:19:18:72 | ... + ... | semmle.label | ... + ... | -| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | semmle.label | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | -| HardcodedCredentials.rb:20:1:20:7 | pw_left | semmle.label | pw_left | -| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | semmle.label | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | -| HardcodedCredentials.rb:21:1:21:8 | pw_right | semmle.label | pw_right | -| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | semmle.label | "4fQuzXef4f2yow8KWvIJTA==" | +| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : String | semmle.label | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : String | +| HardcodedCredentials.rb:20:1:20:7 | pw_left : String | semmle.label | pw_left : String | +| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : String | semmle.label | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : String | +| HardcodedCredentials.rb:21:1:21:8 | pw_right : String | semmle.label | pw_right : String | +| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" : String | semmle.label | "4fQuzXef4f2yow8KWvIJTA==" : String | | HardcodedCredentials.rb:22:1:22:2 | pw | semmle.label | pw | -| HardcodedCredentials.rb:22:6:22:12 | pw_left | semmle.label | pw_left | +| HardcodedCredentials.rb:22:6:22:12 | pw_left : String | semmle.label | pw_left : String | | HardcodedCredentials.rb:22:6:22:23 | ... + ... | semmle.label | ... + ... | -| HardcodedCredentials.rb:22:16:22:23 | pw_right | semmle.label | pw_right | +| HardcodedCredentials.rb:22:16:22:23 | pw_right : String | semmle.label | pw_right : String | | HardcodedCredentials.rb:23:19:23:20 | pw | semmle.label | pw | | HardcodedCredentials.rb:31:18:31:23 | passwd | semmle.label | passwd | -| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | semmle.label | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | +| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : String | semmle.label | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : String | | HardcodedCredentials.rb:43:18:43:25 | username | semmle.label | username | -| HardcodedCredentials.rb:43:29:43:43 | "user@test.com" | semmle.label | "user@test.com" | +| HardcodedCredentials.rb:43:29:43:43 | "user@test.com" : String | semmle.label | "user@test.com" : String | | HardcodedCredentials.rb:43:46:43:53 | password | semmle.label | password | -| HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" | semmle.label | "abcdef123456" | +| HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" : String | semmle.label | "abcdef123456" : String | subpaths #select | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | This hardcoded value is $@. | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | used as credentials | | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | This hardcoded value is $@. | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | used as credentials | -| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | -| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:1:33:1:36 | cert | This hardcoded value is $@. | HardcodedCredentials.rb:1:33:1:36 | cert | used as credentials | +| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : String | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | This hardcoded value is $@. | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | used as credentials | -| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | -| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | -| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | -| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | HardcodedCredentials.rb:31:18:31:23 | passwd | This hardcoded value is $@. | HardcodedCredentials.rb:31:18:31:23 | passwd | used as credentials | -| HardcodedCredentials.rb:43:29:43:43 | "user@test.com" | HardcodedCredentials.rb:43:29:43:43 | "user@test.com" | HardcodedCredentials.rb:43:18:43:25 | username | This hardcoded value is $@. | HardcodedCredentials.rb:43:18:43:25 | username | used as credentials | -| HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" | HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" | HardcodedCredentials.rb:43:46:43:53 | password | This hardcoded value is $@. | HardcodedCredentials.rb:43:46:43:53 | password | used as credentials | +| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : String | HardcodedCredentials.rb:1:33:1:36 | cert | This hardcoded value is $@. | HardcodedCredentials.rb:1:33:1:36 | cert | used as credentials | +| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : String | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | +| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : String | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | +| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" : String | HardcodedCredentials.rb:1:23:1:30 | password | This hardcoded value is $@. | HardcodedCredentials.rb:1:23:1:30 | password | used as credentials | +| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : String | HardcodedCredentials.rb:31:18:31:23 | passwd | This hardcoded value is $@. | HardcodedCredentials.rb:31:18:31:23 | passwd | used as credentials | +| HardcodedCredentials.rb:43:29:43:43 | "user@test.com" | HardcodedCredentials.rb:43:29:43:43 | "user@test.com" : String | HardcodedCredentials.rb:43:18:43:25 | username | This hardcoded value is $@. | HardcodedCredentials.rb:43:18:43:25 | username | used as credentials | +| HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" | HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" : String | HardcodedCredentials.rb:43:46:43:53 | password | This hardcoded value is $@. | HardcodedCredentials.rb:43:46:43:53 | password | used as credentials | diff --git a/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected b/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected index 82fbafcfc89e..fc5b3ebfa149 100644 --- a/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected +++ b/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected @@ -1,16 +1,17 @@ +testFailures failures edges -| insecure_download.rb:31:5:31:7 | url | insecure_download.rb:33:15:33:17 | url | -| insecure_download.rb:31:5:31:7 | url | insecure_download.rb:33:15:33:17 | url | -| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | insecure_download.rb:31:5:31:7 | url | -| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | insecure_download.rb:31:5:31:7 | url | +| insecure_download.rb:31:5:31:7 | url : String | insecure_download.rb:33:15:33:17 | url | +| insecure_download.rb:31:5:31:7 | url : String | insecure_download.rb:33:15:33:17 | url | +| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | insecure_download.rb:31:5:31:7 | url : String | +| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | insecure_download.rb:31:5:31:7 | url : String | nodes | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | semmle.label | "http://example.org/unsafe.APK" | | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | semmle.label | "http://example.org/unsafe.APK" | -| insecure_download.rb:31:5:31:7 | url | semmle.label | url | -| insecure_download.rb:31:5:31:7 | url | semmle.label | url | -| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | semmle.label | "http://example.org/unsafe.APK" | -| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | semmle.label | "http://example.org/unsafe.APK" | +| insecure_download.rb:31:5:31:7 | url : String | semmle.label | url : String | +| insecure_download.rb:31:5:31:7 | url : String | semmle.label | url : String | +| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | semmle.label | "http://example.org/unsafe.APK" : String | +| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | semmle.label | "http://example.org/unsafe.APK" : String | | insecure_download.rb:33:15:33:17 | url | semmle.label | url | | insecure_download.rb:33:15:33:17 | url | semmle.label | url | | insecure_download.rb:37:42:37:68 | "http://example.org/unsafe" | semmle.label | "http://example.org/unsafe" | @@ -18,12 +19,11 @@ nodes | insecure_download.rb:43:22:43:56 | "http://example.org/unsafe.unk..." | semmle.label | "http://example.org/unsafe.unk..." | | insecure_download.rb:53:65:53:78 | "/myscript.sh" | semmle.label | "/myscript.sh" | subpaths -testFailures #select | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | $@ | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | "http://example.org/unsafe.APK" | | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | $@ | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | "http://example.org/unsafe.APK" | -| insecure_download.rb:33:15:33:17 | url | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | insecure_download.rb:33:15:33:17 | url | $@ | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | "http://example.org/unsafe.APK" | -| insecure_download.rb:33:15:33:17 | url | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | insecure_download.rb:33:15:33:17 | url | $@ | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" | "http://example.org/unsafe.APK" | +| insecure_download.rb:33:15:33:17 | url | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | insecure_download.rb:33:15:33:17 | url | $@ | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | "http://example.org/unsafe.APK" : String | +| insecure_download.rb:33:15:33:17 | url | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | insecure_download.rb:33:15:33:17 | url | $@ | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : String | "http://example.org/unsafe.APK" : String | | insecure_download.rb:33:15:33:17 | url | insecure_download.rb:33:15:33:17 | url | insecure_download.rb:33:15:33:17 | url | $@ | insecure_download.rb:33:15:33:17 | url | url | | insecure_download.rb:33:15:33:17 | url | insecure_download.rb:33:15:33:17 | url | insecure_download.rb:33:15:33:17 | url | $@ | insecure_download.rb:33:15:33:17 | url | url | | insecure_download.rb:37:42:37:68 | "http://example.org/unsafe" | insecure_download.rb:37:42:37:68 | "http://example.org/unsafe" | insecure_download.rb:37:42:37:68 | "http://example.org/unsafe" | $@ | insecure_download.rb:37:42:37:68 | "http://example.org/unsafe" | "http://example.org/unsafe" | diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll index 374d42e9ad59..2796a47eec2a 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll @@ -13,6 +13,9 @@ signature module InputSig { /** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */ default predicate uniqueCallEnclosingCallableExclude(DataFlowLang::DataFlowCall call) { none() } + /** Holds if `n` should be excluded from the consistency test `uniqueType`. */ + default predicate uniqueTypeExclude(DataFlowLang::Node n) { none() } + /** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */ default predicate uniqueNodeLocationExclude(DataFlowLang::Node n) { none() } @@ -122,6 +125,7 @@ module MakeConsistency< n instanceof RelevantNode and c = count(getNodeType(n)) and c != 1 and + not Input::uniqueTypeExclude(n) and msg = "Node should have one type but has " + c + "." ) } From 102fb657b3519799ea5ae54ffee1e96153e3d8f8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 22 Jan 2024 15:00:49 +0100 Subject: [PATCH 9/9] temp --- .../cpp/dataflow/internal/DataFlowImpl1.qll | 6 ++ .../cpp/dataflow/internal/DataFlowImpl2.qll | 6 ++ .../cpp/dataflow/internal/DataFlowImpl3.qll | 6 ++ .../cpp/dataflow/internal/DataFlowImpl4.qll | 6 ++ .../dataflow/internal/DataFlowImplLocal.qll | 6 ++ .../ir/dataflow/internal/DataFlowImpl1.qll | 6 ++ .../ir/dataflow/internal/DataFlowImpl2.qll | 6 ++ .../ir/dataflow/internal/DataFlowImpl3.qll | 6 ++ .../ir/dataflow/internal/DataFlowImpl4.qll | 6 ++ .../dataflow/internal/DataFlowImpl1.qll | 6 ++ .../dataflow/internal/DataFlowImpl2.qll | 6 ++ .../dataflow/internal/DataFlowImpl3.qll | 6 ++ .../dataflow/internal/DataFlowImpl4.qll | 6 ++ .../dataflow/internal/DataFlowImpl5.qll | 6 ++ .../go/dataflow/internal/DataFlowImpl1.qll | 6 ++ .../go/dataflow/internal/DataFlowImpl2.qll | 6 ++ .../java/dataflow/internal/DataFlowImpl1.qll | 6 ++ .../java/dataflow/internal/DataFlowImpl2.qll | 6 ++ .../java/dataflow/internal/DataFlowImpl3.qll | 6 ++ .../java/dataflow/internal/DataFlowImpl4.qll | 6 ++ .../java/dataflow/internal/DataFlowImpl5.qll | 6 ++ .../java/dataflow/internal/DataFlowImpl6.qll | 6 ++ .../dataflow/new/internal/DataFlowImpl1.qll | 6 ++ .../dataflow/new/internal/DataFlowImpl2.qll | 6 ++ .../dataflow/new/internal/DataFlowImpl3.qll | 6 ++ .../dataflow/new/internal/DataFlowImpl4.qll | 6 ++ .../ruby/dataflow/internal/DataFlowImpl1.qll | 6 ++ .../ruby/dataflow/internal/DataFlowImpl2.qll | 6 ++ .../dataflow/internal/DataFlowPrivate.qll | 9 +++ .../internal/TaintTrackingImplSpecific.qll | 7 +- .../internal/TaintTrackingPrivate.qll | 51 ++++++++++--- .../dataflow/global/Flow.expected | 26 +++++++ .../library-tests/dataflow/global/taint.rb | 23 ++++++ shared/dataflow/codeql/dataflow/DataFlow.qll | 16 +++++ .../codeql/dataflow/TaintTracking.qll | 29 ++++++++ .../codeql/dataflow/internal/DataFlowImpl.qll | 71 +++++++++++++++++-- .../swift/dataflow/internal/DataFlowImpl1.qll | 6 ++ 37 files changed, 390 insertions(+), 16 deletions(-) create mode 100644 ruby/ql/test/library-tests/dataflow/global/taint.rb diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index ed90e13fec3d..5a20996c7df4 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -1992,6 +1992,15 @@ private predicate isHashClass(DataFlowType t) { t = TModuleDataFlowType(any(TypeInference::HashClass m).getADescendent()) } +pragma[nomagic] +predicate isStringClass(DataFlowType t, boolean descendant) { + t = TModuleDataFlowType(any(TypeInference::StringClass s)) and + descendant = false + or + t = TModuleDataFlowType(any(TypeInference::StringClass s).getAnImmediateDescendent+()) and + descendant = true +} + private predicate isCollectionClass(DataFlowType t) { isArrayClass(t) or isHashClass(t) } predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingImplSpecific.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingImplSpecific.qll index fe733ee5d95a..055d944fbabb 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingImplSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingImplSpecific.qll @@ -6,5 +6,10 @@ private import codeql.dataflow.TaintTracking private import DataFlowImplSpecific module RubyTaintTracking implements InputSig { - import TaintTrackingPrivate + private import TaintTrackingPrivate as Priv + import Priv + + predicate defaultAdditionalTypedLocalTaintStep = Priv::defaultAdditionalTypedLocalTaintStep/2; + + predicate defaultAdditionalTypedLocalTaintStep = Priv::defaultAdditionalTypedLocalTaintStep/4; } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll index a8157ba55db0..070724cb7cfa 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll @@ -72,6 +72,26 @@ private module Cached { cached predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() } + cached + predicate readElementStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // Although flow through collections is modeled precisely using stores/reads, we still + // allow flow out of a _tainted_ collection. This is needed in order to support taint- + // tracking configurations where the source is a collection. + exists(DataFlow::ContentSet c | + readStep(nodeFrom, c, nodeTo) and + c.isElement() + ) + } + + cached + predicate summaryLocalStep( + DataFlow::Node nodeFrom, DataFlow::Node nodeTo, FlowSummaryImpl::Public::SummarizedCallable c + ) { + FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), + nodeTo.(FlowSummaryNode).getSummaryNode(), false) and + c = nodeFrom.(FlowSummaryNode).getSummarizedCallable() + } + /** * Holds if the additional step from `nodeFrom` to `nodeTo` should be included * in all global taint flow configurations. @@ -105,18 +125,18 @@ private module Cached { ) ) or - FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), - nodeTo.(FlowSummaryNode).getSummaryNode(), false) + summaryLocalStep(nodeFrom, nodeTo, _) or any(FlowSteps::AdditionalTaintStep s).step(nodeFrom, nodeTo) or - // Although flow through collections is modeled precisely using stores/reads, we still - // allow flow out of a _tainted_ collection. This is needed in order to support taint- - // tracking configurations where the source is a collection. - exists(DataFlow::ContentSet c | - readStep(nodeFrom, c, nodeTo) and - c.isElement() - ) + readElementStep(nodeFrom, nodeTo) + } + + cached + predicate defaultAdditionalTypedLocalStringStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + readElementStep(nodeFrom, nodeTo) + or + summaryLocalStep(nodeFrom, nodeTo, "[]") } cached @@ -141,3 +161,16 @@ private module Cached { } import Cached + +predicate defaultAdditionalTypedLocalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + defaultAdditionalTypedLocalStringStep(node1, node2) +} + +bindingset[node1, t1] +predicate defaultAdditionalTypedLocalTaintStep( + DataFlow::Node node1, DataFlowType t1, DataFlow::Node node2, DataFlowType t2 +) { + defaultAdditionalTypedLocalStringStep(node1, node2) and + isStringClass(t1, false) and + t2 = t1 +} diff --git a/ruby/ql/test/library-tests/dataflow/global/Flow.expected b/ruby/ql/test/library-tests/dataflow/global/Flow.expected index 2716ec929ef1..6b4ab7442afb 100644 --- a/ruby/ql/test/library-tests/dataflow/global/Flow.expected +++ b/ruby/ql/test/library-tests/dataflow/global/Flow.expected @@ -259,6 +259,17 @@ edges | instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:120:6:120:20 | call to get_field | | instance_variables.rb:121:1:121:3 | bar | instance_variables.rb:122:6:122:8 | bar | | instance_variables.rb:121:7:121:24 | call to new | instance_variables.rb:121:1:121:3 | bar | +| taint.rb:9:15:9:15 | x | taint.rb:12:13:12:13 | x : String | +| taint.rb:12:13:12:13 | x : String | taint.rb:10:5:15:11 | case ... : String | +| taint.rb:19:1:19:1 | x : String | taint.rb:20:6:20:6 | x | +| taint.rb:19:1:19:1 | x : String | taint.rb:22:5:22:5 | x : String | +| taint.rb:19:5:19:25 | call to stringify : String | taint.rb:19:1:19:1 | x : String | +| taint.rb:19:15:19:25 | ( ... ) | taint.rb:9:15:9:15 | x | +| taint.rb:19:15:19:25 | ( ... ) | taint.rb:19:5:19:25 | call to stringify : String | +| taint.rb:19:16:19:24 | call to taint | taint.rb:19:15:19:25 | ( ... ) | +| taint.rb:22:1:22:1 | y : String | taint.rb:23:6:23:6 | y | +| taint.rb:22:5:22:5 | x : String | taint.rb:22:5:22:11 | ...[...] : String | +| taint.rb:22:5:22:11 | ...[...] : String | taint.rb:22:1:22:1 | y : String | nodes | blocks.rb:8:10:8:14 | yield ... | semmle.label | yield ... | | blocks.rb:14:12:14:20 | call to source | semmle.label | call to source | @@ -486,6 +497,18 @@ nodes | instance_variables.rb:121:1:121:3 | bar | semmle.label | bar | | instance_variables.rb:121:7:121:24 | call to new | semmle.label | call to new | | instance_variables.rb:122:6:122:8 | bar | semmle.label | bar | +| taint.rb:9:15:9:15 | x | semmle.label | x | +| taint.rb:10:5:15:11 | case ... : String | semmle.label | case ... : String | +| taint.rb:12:13:12:13 | x : String | semmle.label | x : String | +| taint.rb:19:1:19:1 | x : String | semmle.label | x : String | +| taint.rb:19:5:19:25 | call to stringify : String | semmle.label | call to stringify : String | +| taint.rb:19:15:19:25 | ( ... ) | semmle.label | ( ... ) | +| taint.rb:19:16:19:24 | call to taint | semmle.label | call to taint | +| taint.rb:20:6:20:6 | x | semmle.label | x | +| taint.rb:22:1:22:1 | y : String | semmle.label | y : String | +| taint.rb:22:5:22:5 | x : String | semmle.label | x : String | +| taint.rb:22:5:22:11 | ...[...] : String | semmle.label | ...[...] : String | +| taint.rb:23:6:23:6 | y | semmle.label | y | subpaths | captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:15:28:15:28 | x | captured_variables.rb:16:5:18:5 | -> { ... } [captured x] | captured_variables.rb:20:2:20:34 | call to capture_escape_return1 [captured x] | | captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:22:28:22:28 | x | captured_variables.rb:23:5:25:5 | -> { ... } [captured x] | captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] | @@ -561,6 +584,7 @@ subpaths | instance_variables.rb:119:28:119:36 | call to taint | instance_variables.rb:27:25:27:29 | field | instance_variables.rb:28:9:28:25 | [post] self [@field] | instance_variables.rb:119:6:119:10 | [post] foo16 [@field] | | instance_variables.rb:120:6:120:10 | foo16 [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:120:6:120:20 | call to get_field | | instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:120:6:120:20 | call to get_field | +| taint.rb:19:15:19:25 | ( ... ) | taint.rb:9:15:9:15 | x | taint.rb:10:5:15:11 | case ... : String | taint.rb:19:5:19:25 | call to stringify : String | #select | blocks.rb:8:10:8:14 | yield ... | blocks.rb:14:12:14:20 | call to source | blocks.rb:8:10:8:14 | yield ... | $@ | blocks.rb:14:12:14:20 | call to source | call to source | | captured_variables.rb:10:20:10:20 | x | captured_variables.rb:13:20:13:29 | call to taint | captured_variables.rb:10:20:10:20 | x | $@ | captured_variables.rb:13:20:13:29 | call to taint | call to taint | @@ -610,3 +634,5 @@ subpaths | instance_variables.rb:119:6:119:37 | call to call_initialize | instance_variables.rb:24:9:24:17 | call to taint | instance_variables.rb:119:6:119:37 | call to call_initialize | $@ | instance_variables.rb:24:9:24:17 | call to taint | call to taint | | instance_variables.rb:120:6:120:20 | call to get_field | instance_variables.rb:119:28:119:36 | call to taint | instance_variables.rb:120:6:120:20 | call to get_field | $@ | instance_variables.rb:119:28:119:36 | call to taint | call to taint | | instance_variables.rb:122:6:122:8 | bar | instance_variables.rb:43:9:43:17 | call to taint | instance_variables.rb:122:6:122:8 | bar | $@ | instance_variables.rb:43:9:43:17 | call to taint | call to taint | +| taint.rb:20:6:20:6 | x | taint.rb:19:16:19:24 | call to taint | taint.rb:20:6:20:6 | x | $@ | taint.rb:19:16:19:24 | call to taint | call to taint | +| taint.rb:23:6:23:6 | y | taint.rb:19:16:19:24 | call to taint | taint.rb:23:6:23:6 | y | $@ | taint.rb:19:16:19:24 | call to taint | call to taint | diff --git a/ruby/ql/test/library-tests/dataflow/global/taint.rb b/ruby/ql/test/library-tests/dataflow/global/taint.rb new file mode 100644 index 000000000000..ebd435d7c488 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/global/taint.rb @@ -0,0 +1,23 @@ +def taint x + x +end + +def sink x + puts "SINK: #{x}" +end + +def stringify x + case x + when String then + x + else + "" + end + end +end + +x = stringify (taint "1") +sink x # $ hasValueFlow=1 + +y = x[0..1] +sink y # $ hasTaintFlow=1 \ No newline at end of file diff --git a/shared/dataflow/codeql/dataflow/DataFlow.qll b/shared/dataflow/codeql/dataflow/DataFlow.qll index 856b68d249c2..30e1c39f8c63 100644 --- a/shared/dataflow/codeql/dataflow/DataFlow.qll +++ b/shared/dataflow/codeql/dataflow/DataFlow.qll @@ -537,6 +537,14 @@ module DataFlowMake { private module C implements FullStateConfigSig { import DefaultState import Config + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep( + Node node1, DataFlowType t1, Node node2, DataFlowType t2 + ) { + none() + } } import Impl @@ -553,6 +561,14 @@ module DataFlowMake { module GlobalWithState implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep( + Node node1, DataFlowType t1, Node node2, DataFlowType t2 + ) { + none() + } } import Impl diff --git a/shared/dataflow/codeql/dataflow/TaintTracking.qll b/shared/dataflow/codeql/dataflow/TaintTracking.qll index 73960fbca1db..8c9ce5a23127 100644 --- a/shared/dataflow/codeql/dataflow/TaintTracking.qll +++ b/shared/dataflow/codeql/dataflow/TaintTracking.qll @@ -28,6 +28,17 @@ signature module InputSig { */ bindingset[node] predicate defaultImplicitTaintRead(Lang::Node node, Lang::ContentSet c); + + default predicate defaultAdditionalTypedLocalTaintStep(Lang::Node node1, Lang::Node node2) { + none() + } + + bindingset[node1, t1] + default predicate defaultAdditionalTypedLocalTaintStep( + Lang::Node node1, Lang::DataFlowType t1, Lang::Node node2, Lang::DataFlowType t2 + ) { + none() + } } /** @@ -63,6 +74,12 @@ module TaintFlowMake TaintTrac ) and defaultImplicitTaintRead(node, c) } + + predicate isAdditionalTypedLocalFlowStep = + TaintTrackingLang::defaultAdditionalTypedLocalTaintStep/2; + + predicate isAdditionalTypedLocalFlowStep = + TaintTrackingLang::defaultAdditionalTypedLocalTaintStep/4; } /** @@ -72,6 +89,12 @@ module TaintFlowMake TaintTrac private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState import Config + + predicate isAdditionalTypedLocalFlowStep = + TaintTrackingLang::defaultAdditionalTypedLocalTaintStep/2; + + predicate isAdditionalTypedLocalFlowStep = + TaintTrackingLang::defaultAdditionalTypedLocalTaintStep/4; } private module C implements DataFlowInternal::FullStateConfigSig { @@ -92,6 +115,12 @@ module TaintFlowMake TaintTrac module GlobalWithState implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config + + predicate isAdditionalTypedLocalFlowStep = + TaintTrackingLang::defaultAdditionalTypedLocalTaintStep/2; + + predicate isAdditionalTypedLocalFlowStep = + TaintTrackingLang::defaultAdditionalTypedLocalTaintStep/4; } private module C implements DataFlowInternal::FullStateConfigSig { diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 27aa1d38e6e4..5ac3e876ffd9 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -68,6 +68,19 @@ module MakeImpl { */ predicate isAdditionalFlowStep(Node node1, Node node2); + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2); + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + bindingset[node1, t1] + predicate isAdditionalTypedLocalFlowStep( + Node node1, DataFlowType t1, Node node2, DataFlowType t2 + ); + /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * This step is only applicable in `state1` and updates the flow state to `state2`. @@ -368,6 +381,16 @@ module MakeImpl { ) } + /** + * Holds if the additional step from `node1` to `node2` does not jump between callables. + */ + bindingset[node1, t1] + private predicate additionalTypedLocalFlowStep( + NodeEx node1, DataFlowType t1, NodeEx node2, DataFlowType t2 + ) { + Config::isAdditionalTypedLocalFlowStep(node1.asNode(), t1, node2.asNode(), t2) + } + private predicate additionalLocalStateStep( NodeEx node1, FlowState s1, NodeEx node2, FlowState s2 ) { @@ -1255,6 +1278,9 @@ module MakeImpl { Typ t, LocalCc lcc ); + bindingset[node1, t1] + predicate localTypedStep(NodeEx node1, Typ t1, NodeEx node2, Typ t2); + bindingset[node, state, t0, ap] predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); @@ -1340,8 +1366,15 @@ module MakeImpl { localStep(mid, state0, node, state, true, _, localCc) and t = t0 or - localStep(mid, state0, node, state, false, t, localCc) and - ap instanceof ApNil + exists(Typ t1 | + localStep(mid, state0, node, state, false, t1, localCc) and + ap instanceof ApNil + | + localTypedStep(mid, t0, node, t) + or + not localTypedStep(mid, t0, node, _) and + t = t1 + ) ) or fwdFlowJump(node, state, t, ap, apa) and @@ -2531,6 +2564,8 @@ module MakeImpl { exists(lcc) } + predicate localTypedStep(NodeEx node1, Typ t1, NodeEx node2, Typ t2) { none() } + pragma[nomagic] private predicate expectsContentCand(NodeEx node) { exists(Content c | @@ -2591,7 +2626,9 @@ module MakeImpl { clearsContentCached(this.asNode(), _) or expectsContentCached(this.asNode(), _) or neverSkipInPathGraph(this.asNode()) or - Config::neverSkip(this.asNode()) + Config::neverSkip(this.asNode()) or + Config::isAdditionalTypedLocalFlowStep(this.asNode(), _) or + Config::isAdditionalTypedLocalFlowStep(_, this.asNode()) } } @@ -2786,6 +2823,11 @@ module MakeImpl { exists(lcc) } + bindingset[node1, t1] + predicate localTypedStep(NodeEx node1, Typ t1, NodeEx node2, Typ t2) { + additionalTypedLocalFlowStep(node1, t1, node2, t2) + } + pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { exists(Content c | @@ -2875,6 +2917,11 @@ module MakeImpl { exists(lcc) } + bindingset[node1, t1] + predicate localTypedStep(NodeEx node1, Typ t1, NodeEx node2, Typ t2) { + additionalTypedLocalFlowStep(node1, t1, node2, t2) + } + pragma[nomagic] private predicate clearSet(NodeEx node, ContentSet c) { PrevStage::revFlow(node) and @@ -3155,6 +3202,11 @@ module MakeImpl { PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } + bindingset[node1, t1] + predicate localTypedStep(NodeEx node1, Typ t1, NodeEx node2, Typ t2) { + additionalTypedLocalFlowStep(node1, t1, node2, t2) + } + bindingset[node, state, t0, ap] predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { strengthenType(node, t0, t) and @@ -3925,10 +3977,17 @@ module MakeImpl { localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and - localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + exists( + NodeEx midnode, FlowState state0, DataFlowType t0, DataFlowType t1, LocalCallContext localCC + | + pathNode(mid, midnode, state0, cc, sc, t0, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t1, localCC) and ap instanceof AccessPathNil + | + additionalTypedLocalFlowStep(midnode, t0, node, t) + or + not additionalTypedLocalFlowStep(midnode, t0, node, _) and + t = t1 ) or jumpStepEx(mid.getNodeEx(), node) and diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..1f7150ed8d7f 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll @@ -296,6 +296,12 @@ deprecated private module Config implements FullStateConfigSig { } predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, Node node2) { none() } + + predicate isAdditionalTypedLocalFlowStep(Node node1, DataFlowType t1, Node node2, DataFlowType t2) { + none() + } } deprecated private import Impl as I