From fea1e47daa6f2d18226297e857e19d0000bc386d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 26 Sep 2022 11:35:17 +0200 Subject: [PATCH 1/4] Ruby: Add data-flow test for spurious flow through a reverse store --- .../dataflow/array-flow/array-flow.expected | 52 +++++++++++++++++++ .../dataflow/array-flow/array_flow.rb | 3 ++ 2 files changed, 55 insertions(+) diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected index 904efed2d94..ec6bf2843f9 100644 --- a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected @@ -3367,6 +3367,10 @@ edges | array_flow.rb:1605:10:1605:10 | c [element] : | array_flow.rb:1605:10:1605:13 | ...[...] | | array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | array_flow.rb:1611:10:1611:10 | a [element, element 0] : | | array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | array_flow.rb:1611:10:1611:10 | a [element, element 0] : | +| array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | array_flow.rb:1614:10:1614:10 | a [element, element 0] : | +| array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | array_flow.rb:1614:10:1614:10 | a [element, element 0] : | +| array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | array_flow.rb:1615:10:1615:10 | a [element, element 0] : | +| array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | array_flow.rb:1615:10:1615:10 | a [element, element 0] : | | array_flow.rb:1610:5:1610:8 | [post] ...[...] [element 0] : | array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | | array_flow.rb:1610:5:1610:8 | [post] ...[...] [element 0] : | array_flow.rb:1610:5:1610:5 | [post] a [element, element 0] : | | array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1610:5:1610:8 | [post] ...[...] [element 0] : | @@ -3375,6 +3379,28 @@ edges | array_flow.rb:1611:10:1611:10 | a [element, element 0] : | array_flow.rb:1611:10:1611:13 | ...[...] [element 0] : | | array_flow.rb:1611:10:1611:13 | ...[...] [element 0] : | array_flow.rb:1611:10:1611:16 | ...[...] | | array_flow.rb:1611:10:1611:13 | ...[...] [element 0] : | array_flow.rb:1611:10:1611:16 | ...[...] | +| array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1614:10:1614:10 | a [element, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1614:10:1614:10 | a [element, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1615:10:1615:10 | a [element, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1615:10:1615:10 | a [element, element 0] : | +| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | +| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | +| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | +| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | +| array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | +| array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | +| array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | +| array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | +| array_flow.rb:1614:10:1614:10 | a [element, element 0] : | array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | +| array_flow.rb:1614:10:1614:10 | a [element, element 0] : | array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | +| array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | array_flow.rb:1614:10:1614:16 | ...[...] | +| array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | array_flow.rb:1614:10:1614:16 | ...[...] | +| array_flow.rb:1615:10:1615:10 | a [element, element 0] : | array_flow.rb:1615:10:1615:13 | ...[...] [element 0] : | +| array_flow.rb:1615:10:1615:10 | a [element, element 0] : | array_flow.rb:1615:10:1615:13 | ...[...] [element 0] : | +| array_flow.rb:1615:10:1615:13 | ...[...] [element 0] : | array_flow.rb:1615:10:1615:16 | ...[...] | +| array_flow.rb:1615:10:1615:13 | ...[...] [element 0] : | array_flow.rb:1615:10:1615:16 | ...[...] | nodes | array_flow.rb:2:9:2:20 | * ... [element 0] : | semmle.label | * ... [element 0] : | | array_flow.rb:2:9:2:20 | * ... [element 0] : | semmle.label | * ... [element 0] : | @@ -7010,6 +7036,28 @@ nodes | array_flow.rb:1611:10:1611:13 | ...[...] [element 0] : | semmle.label | ...[...] [element 0] : | | array_flow.rb:1611:10:1611:16 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1611:10:1611:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | semmle.label | [post] a [element 1, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | semmle.label | [post] a [element 1, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | semmle.label | [post] a [element, element 0] : | +| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | semmle.label | [post] a [element, element 0] : | +| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | semmle.label | [post] ...[...] [element 0] : | +| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | semmle.label | [post] ...[...] [element 0] : | +| array_flow.rb:1613:15:1613:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:1613:15:1613:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | semmle.label | a [element 1, element 0] : | +| array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | semmle.label | a [element 1, element 0] : | +| array_flow.rb:1614:10:1614:10 | a [element, element 0] : | semmle.label | a [element, element 0] : | +| array_flow.rb:1614:10:1614:10 | a [element, element 0] : | semmle.label | a [element, element 0] : | +| array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | semmle.label | ...[...] [element 0] : | +| array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | semmle.label | ...[...] [element 0] : | +| array_flow.rb:1614:10:1614:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1614:10:1614:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1615:10:1615:10 | a [element, element 0] : | semmle.label | a [element, element 0] : | +| array_flow.rb:1615:10:1615:10 | a [element, element 0] : | semmle.label | a [element, element 0] : | +| array_flow.rb:1615:10:1615:13 | ...[...] [element 0] : | semmle.label | ...[...] [element 0] : | +| array_flow.rb:1615:10:1615:13 | ...[...] [element 0] : | semmle.label | ...[...] [element 0] : | +| array_flow.rb:1615:10:1615:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1615:10:1615:16 | ...[...] | semmle.label | ...[...] | subpaths #select | array_flow.rb:3:10:3:13 | ...[...] | array_flow.rb:2:10:2:20 | call to source : | array_flow.rb:3:10:3:13 | ...[...] | $@ | array_flow.rb:2:10:2:20 | call to source : | call to source : | @@ -7694,3 +7742,7 @@ subpaths | array_flow.rb:1605:10:1605:13 | ...[...] | array_flow.rb:1600:16:1600:28 | call to source : | array_flow.rb:1605:10:1605:13 | ...[...] | $@ | array_flow.rb:1600:16:1600:28 | call to source : | call to source : | | array_flow.rb:1605:10:1605:13 | ...[...] | array_flow.rb:1601:13:1601:25 | call to source : | array_flow.rb:1605:10:1605:13 | ...[...] | $@ | array_flow.rb:1601:13:1601:25 | call to source : | call to source : | | array_flow.rb:1611:10:1611:16 | ...[...] | array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1611:10:1611:16 | ...[...] | $@ | array_flow.rb:1610:15:1610:27 | call to source : | call to source : | +| array_flow.rb:1614:10:1614:16 | ...[...] | array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1614:10:1614:16 | ...[...] | $@ | array_flow.rb:1610:15:1610:27 | call to source : | call to source : | +| array_flow.rb:1614:10:1614:16 | ...[...] | array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1614:10:1614:16 | ...[...] | $@ | array_flow.rb:1613:15:1613:27 | call to source : | call to source : | +| array_flow.rb:1615:10:1615:16 | ...[...] | array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1615:10:1615:16 | ...[...] | $@ | array_flow.rb:1610:15:1610:27 | call to source : | call to source : | +| array_flow.rb:1615:10:1615:16 | ...[...] | array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1615:10:1615:16 | ...[...] | $@ | array_flow.rb:1613:15:1613:27 | call to source : | call to source : | diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb b/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb index 37e974eab2f..aa10ce09fae 100644 --- a/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb +++ b/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb @@ -1610,4 +1610,7 @@ def m136(i) a[i][0] = source(136.1) sink(a[0][0]) # $ hasValueFlow=136.1 sink(a[0][1]) + a[1][0] = source(136.2) + sink(a[1][0]) # $ hasValueFlow=136.2 $ SPURIOUS hasValueFlow=136.1 + sink(a[2][0]) # $ hasValueFlow=136.1 $ SPURIOUS hasValueFlow=136.2 end From 2351c0288a8158211e47b17e65a8ee611e032587 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 26 Sep 2022 19:35:36 +0200 Subject: [PATCH 2/4] Ruby: Fix spurious flow through reverse stores --- .../lib/codeql/ruby/dataflow/FlowSummary.qll | 21 ++- .../dataflow/internal/DataFlowPrivate.qll | 6 +- .../ruby/dataflow/internal/DataFlowPublic.qll | 61 ++++++++- .../internal/FlowSummaryImplSpecific.qll | 40 ++++-- .../lib/codeql/ruby/frameworks/core/Array.qll | 129 +++++++++--------- .../lib/codeql/ruby/frameworks/core/Hash.qll | 27 +--- .../dataflow/array-flow/array-flow.expected | 9 -- .../dataflow/array-flow/array_flow.rb | 2 +- 8 files changed, 184 insertions(+), 111 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll b/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll index 55cad66e060..b9e010416c8 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll @@ -45,6 +45,17 @@ module SummaryComponent { result = SC::content(TSingletonContent(DataFlow::Content::getElementContent(cv))) } + /** + * Gets a summary component that represents an element in a collection at a specific + * known index `cv`, or an uknown index. + */ + SummaryComponent elementKnownOrUnknown(ConstantValue cv) { + result = SC::content(TKnownOrUnknownElementContent(TKnownElementContent(cv))) + or + not exists(TKnownElementContent(cv)) and + result = elementUnknown() + } + /** * Gets a summary component that represents an element in a collection at either an unknown * index or known index. This has the same semantics as @@ -62,7 +73,15 @@ module SummaryComponent { * integer index `lower` or above. */ SummaryComponent elementLowerBound(int lower) { - result = SC::content(TElementLowerBoundContent(lower)) + result = SC::content(TElementLowerBoundContent(lower, false)) + } + + /** + * Gets a summary component that represents an element in a collection at known + * integer index `lower` or above, or possibly at an unknown index. + */ + SummaryComponent elementLowerBoundOrUnknown(int lower) { + result = SC::content(TElementLowerBoundContent(lower, true)) } /** Gets a summary component that represents a value in a pair at an unknown key. */ diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 5652b700851..bb2f256a08d 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -380,8 +380,10 @@ private module Cached { newtype TContentSet = TSingletonContent(Content c) or TAnyElementContent() or - TElementLowerBoundContent(int lower) { - FlowSummaryImplSpecific::ParsePositions::isParsedElementLowerBoundPosition(_, lower) + TKnownOrUnknownElementContent(Content::KnownElementContent c) or + TElementLowerBoundContent(int lower, boolean includeUnknown) { + FlowSummaryImplSpecific::ParsePositions::isParsedElementLowerBoundPosition(_, includeUnknown, + lower) } cached diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll index 3b0c0094386..47f0b9bdef1 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll @@ -329,11 +329,28 @@ class ContentSet extends TContentSet { /** Holds if this content set represents all `ElementContent`s. */ predicate isAnyElement() { this = TAnyElementContent() } + /** + * Holds if this content set represents a specific known element index, or an + * unknown element index. + */ + predicate isKnownOrUnknownElement(Content::KnownElementContent c) { + this = TKnownOrUnknownElementContent(c) + } + /** * Holds if this content set represents all `KnownElementContent`s where * the index is an integer greater than or equal to `lower`. */ - predicate isElementLowerBound(int lower) { this = TElementLowerBoundContent(lower) } + predicate isElementLowerBound(int lower) { this = TElementLowerBoundContent(lower, false) } + + /** + * Holds if this content set represents `UnknownElementContent` unioned with + * all `KnownElementContent`s where the index is an integer greater than or + * equal to `lower`. + */ + predicate isElementLowerBoundOrUnknown(int lower) { + this = TElementLowerBoundContent(lower, true) + } /** Gets a textual representation of this content set. */ string toString() { @@ -345,8 +362,18 @@ class ContentSet extends TContentSet { this.isAnyElement() and result = "any element" or - exists(int lower | - this.isElementLowerBound(lower) and + exists(Content::KnownElementContent c | + this.isKnownOrUnknownElement(c) and + result = c + " or unknown" + ) + or + exists(int lower, boolean includeUnknown | + this = TElementLowerBoundContent(lower, includeUnknown) + | + includeUnknown = false and + result = lower + "..!" + or + includeUnknown = true and result = lower + ".." ) } @@ -355,9 +382,18 @@ class ContentSet extends TContentSet { Content getAStoreContent() { this.isSingleton(result) or + // For reverse stores, `a[unknown][0] = x`, it is important that the read-step + // from `a` to `a[unknown]` (which can read any element), gets translated into + // a reverse store step that store only into `?` this.isAnyElement() and result = TUnknownElementContent() or + // For reverse stores, `a[1][0] = x`, it is important that the read-step + // from `a` to `a[1]` (which can read both elements stored at exactly index `1` + // and elements stored at unknown index), gets translated into a reverse store + // step that store only into `1` + this.isKnownOrUnknownElement(result) + or this.isElementLowerBound(_) and result = TUnknownElementContent() } @@ -369,10 +405,21 @@ class ContentSet extends TContentSet { this.isAnyElement() and result instanceof Content::ElementContent or - exists(int lower, int i | - this.isElementLowerBound(lower) and - result.(Content::KnownElementContent).getIndex().isInt(i) and - i >= lower + exists(Content::KnownElementContent c | this.isKnownOrUnknownElement(c) | + result = c or + result = TUnknownElementContent() + ) + or + exists(int lower, boolean includeUnknown | + this = TElementLowerBoundContent(lower, includeUnknown) + | + exists(int i | + result.(Content::KnownElementContent).getIndex().isInt(i) and + i >= lower + ) + or + includeUnknown = true and + result = TUnknownElementContent() ) } } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll index a9aef4bf8e3..9926bfdf98d 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll @@ -74,16 +74,30 @@ private SummaryComponent interpretElementArg(string arg) { arg = "any" and result = FlowSummary::SummaryComponent::elementAny() or - exists(int lower | - ParsePositions::isParsedElementLowerBoundPosition(arg, lower) and + exists(int lower, boolean includeUnknown | + ParsePositions::isParsedElementLowerBoundPosition(arg, includeUnknown, lower) + | + includeUnknown = false and result = FlowSummary::SummaryComponent::elementLowerBound(lower) + or + includeUnknown = true and + result = FlowSummary::SummaryComponent::elementLowerBoundOrUnknown(lower) ) or - exists(ConstantValue cv | result = FlowSummary::SummaryComponent::elementKnown(cv) | - cv.isInt(AccessPath::parseInt(arg)) + exists(ConstantValue cv, string argAdjusted, boolean includeUnknown | + argAdjusted = ParsePositions::adjustElementArgument(arg, includeUnknown) and + ( + includeUnknown = false and + result = FlowSummary::SummaryComponent::elementKnown(cv) + or + includeUnknown = true and + result = FlowSummary::SummaryComponent::elementKnownOrUnknown(cv) + ) + | + cv.isInt(AccessPath::parseInt(argAdjusted)) or - not exists(AccessPath::parseInt(arg)) and - cv.serialize() = arg + not exists(AccessPath::parseInt(argAdjusted)) and + cv.serialize() = argAdjusted ) } @@ -277,9 +291,19 @@ module ParsePositions { c = paramName + ":" } - predicate isParsedElementLowerBoundPosition(string c, int lower) { + bindingset[arg] + string adjustElementArgument(string arg, boolean includeUnknown) { + result = arg.regexpCapture("(.*)!", 1) and + includeUnknown = false + or + result = arg and + not arg.matches("%!") and + includeUnknown = true + } + + predicate isParsedElementLowerBoundPosition(string c, boolean includeUnknown, int lower) { isElementBody(c) and - lower = AccessPath::parseLowerBound(c) + lower = AccessPath::parseLowerBound(adjustElementArgument(c, includeUnknown)) } } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll b/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll index ba7564a65e6..1ecdda2cb48 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll @@ -193,7 +193,7 @@ module Array { } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].Element[?," + index.serialize() + "]" and + input = "Argument[self].Element[" + index.serialize() + "]" and output = "ReturnValue" and preservesValue = true } @@ -258,7 +258,7 @@ module Array { output = "ReturnValue" or exists(ArrayIndex i | i >= start and i <= end | - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "ReturnValue.Element[" + (i - start) + "]" ) ) @@ -290,7 +290,7 @@ module Array { } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].Element[?,0..]" and + input = "Argument[self].Element[0..]" and output = "ReturnValue.Element[?]" and preservesValue = true } @@ -321,7 +321,7 @@ module Array { output = "Argument[self].Element[" + index.serialize() + "]" and preservesValue = true or - input = "Argument[self].WithoutElement[" + index.serialize() + "]" and + input = "Argument[self].WithoutElement[" + index.serialize() + "!]" and output = "Argument[self]" and preservesValue = true } @@ -401,7 +401,7 @@ module Array { } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].Element[" + index.serialize() + ",?]" and + input = "Argument[self].Element[" + index.serialize() + "]" and output = "ReturnValue" and preservesValue = true } @@ -484,7 +484,7 @@ module Array { CompactBangSummary() { this = "compact!" } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].Element[?,0..]" and + input = "Argument[self].Element[0..]" and output = ["ReturnValue.Element[?]", "Argument[self].Element[?]"] and preservesValue = true } @@ -552,18 +552,18 @@ module Array { if index.isInt(_) then // array indices may get shifted - input = "Argument[self].WithoutElement[" + index.serialize() + "].Element[0..]" and + input = "Argument[self].WithoutElement[" + index.serialize() + "!].Element[0..!]" and output = "Argument[self].Element[?]" or - input = "Argument[self].WithoutElement[0..]" and + input = "Argument[self].WithoutElement[0..!]" and output = "Argument[self]" else ( - input = "Argument[self].WithoutElement[" + index.serialize() + "]" and + input = "Argument[self].WithoutElement[" + index.serialize() + "!]" and output = "Argument[self]" ) ) or - input = "Argument[self].Element[" + index.serialize() + ",?]" and + input = "Argument[self].Element[" + index.serialize() + "]" and output = "ReturnValue" ) and preservesValue = true @@ -581,10 +581,10 @@ module Array { or ( // array indices may get shifted - input = "Argument[self].Element[0..]" and + input = "Argument[self].Element[0..!]" and output = "Argument[self].Element[?]" or - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = "Argument[self]" or input = "Argument[self].Element[any]" and @@ -625,19 +625,16 @@ module Array { input = "Argument[self].Element[?]" and output = ["ReturnValue", "Argument[self].Element[?]"] or - input = "Argument[self].Element[" + i + "]" and - output = "ReturnValue" - or - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "ReturnValue" or exists(ArrayIndex j | j < i and - input = "Argument[self].WithElement[" + j + "]" and + input = "Argument[self].WithElement[" + j + "!]" and output = "Argument[self]" or j > i and - input = "Argument[self].Element[" + j + "]" and + input = "Argument[self].Element[" + j + "!]" and output = "Argument[self].Element[" + (j - 1) + "]" ) ) and @@ -674,10 +671,10 @@ module Array { output = "Argument[block].Parameter[" + lastBlockParam + "]" or // array indices may get shifted - input = "Argument[self].Element[0..]" and + input = "Argument[self].Element[0..!]" and output = ["ReturnValue.Element[?]", "Argument[self].Element[?]"] or - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = ["ReturnValue", "Argument[self]"] ) and preservesValue = true @@ -713,7 +710,7 @@ module Array { private string buildDigInputSpecComponent(RelevantDigMethodCall dig, int i) { exists(string s | s = getDigArg(dig, i) and - if s = "?" then result = "any" else result = s + ",?" + if s = "?" then result = "any" else result = s ) } @@ -805,7 +802,7 @@ module Array { override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { ( - input = "Argument[self].Element[?," + index.serialize() + "]" and + input = "Argument[self].Element[" + index.serialize() + "]" and output = "ReturnValue" or input = "Argument[0]" and @@ -955,13 +952,13 @@ module Array { exists(ArrayIndex j | // Existing elements before the insertion point are unaffected. j < i and - input = "Argument[self].WithElement[" + j + "]" and + input = "Argument[self].WithElement[" + j + "!]" and output = r or // Existing elements after the insertion point are shifted by however // many values we're inserting. j >= i and - input = "Argument[self].Element[" + j + "]" and + input = "Argument[self].Element[" + j + "!]" and output = r + ".Element[" + (j + numValues) + "]" ) or @@ -1028,10 +1025,10 @@ module Array { output = "Argument[self]" or // array indices may get shifted - input = "Argument[self].Element[0..]" and + input = "Argument[self].Element[0..!]" and output = ["ReturnValue.Element[?]", "Argument[self].Element[?]"] or - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = ["ReturnValue", "Argument[self]"] or input = "Argument[self].Element[any]" and @@ -1144,7 +1141,7 @@ module Array { override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { exists(int num | num = mc.getNumberOfArguments() and preservesValue = true | exists(ArrayIndex i | - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "Argument[self].Element[" + (i + num) + "]" ) or @@ -1208,10 +1205,10 @@ module Array { override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { ( // array indices may get shifted - input = "Argument[self].Element[0..]" and + input = "Argument[self].Element[0..!]" and output = ["ReturnValue.Element[?]", "Argument[self].Element[?]"] or - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = ["ReturnValue", "Argument[self]"] or input = "Argument[self].Element[any]" and @@ -1281,7 +1278,7 @@ module Array { output = "ReturnValue.Element[?]" or exists(ArrayIndex i | - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and ( i < c and output = "ReturnValue.Element[?]" or @@ -1339,7 +1336,7 @@ module Array { output = r + ".Element[?]" or exists(ArrayIndex i | - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and ( i < c and output = r + ".Element[?]" or @@ -1385,10 +1382,10 @@ module Array { output = "Argument[block].Parameter[" + lastBlockParam + "]" or // array indices may get shifted - input = "Argument[self].Element[0..]" and + input = "Argument[self].Element[0..!]" and output = ["ReturnValue.Element[?]", "Argument[self].Element[?]"] or - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = ["ReturnValue", "Argument[self]"] or input = "Argument[self].WithoutElement[any]" and @@ -1421,7 +1418,7 @@ module Array { or preservesValue = true and ( - input = "Argument[self].WithoutElement[0..]" and + input = "Argument[self].WithoutElement[0..!]" and output = "Argument[self]" or input = "Argument[self].Element[?]" and @@ -1431,10 +1428,10 @@ module Array { "ReturnValue.Element[1]" // hash ] or - input = "Argument[self].WithoutElement[0..].WithoutElement[?].Element[any]" and + input = "Argument[self].WithoutElement[0..!].WithoutElement[?].Element[any]" and output = "ReturnValue.Element[1]" or - exists(ArrayIndex i | input = "Argument[self].Element[" + i + "]" | + exists(ArrayIndex i | input = "Argument[self].Element[" + i + "!]" | i = 0 and output = "ReturnValue" or i > 0 and output = "Argument[self].Element[" + (i - 1) + "]" @@ -1461,11 +1458,11 @@ module Array { or exists(ArrayIndex i | i < n and - input = "Argument[self].WithElement[" + i + "]" and + input = "Argument[self].WithElement[" + i + "!]" and output = "ReturnValue" or i >= n and - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "Argument[self].Element[" + (i - n) + "]" ) ) @@ -1539,15 +1536,15 @@ module Array { input = "Argument[self].Element[?]" and output = ["ReturnValue", "Argument[self].Element[?]"] or - input = "Argument[self].Element[" + n + "]" and output = "ReturnValue" + input = "Argument[self].Element[" + n + "!]" and output = "ReturnValue" or exists(ArrayIndex i | i < n and - input = "Argument[self].WithElement[" + i + "]" and + input = "Argument[self].WithElement[" + i + "!]" and output = "Argument[self]" or i > n and - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "Argument[self].Element[" + (i - 1) + "]" ) ) @@ -1619,16 +1616,16 @@ module Array { or exists(ArrayIndex i | i < start and - input = "Argument[self].WithElement[" + i + "]" and + input = "Argument[self].WithElement[" + i + "!]" and output = "Argument[self]" or i >= start and i <= end and - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "ReturnValue.Element[" + (i - start) + "]" or i > end and - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "Argument[self].Element[" + (i - (end - start + 1)) + "]" ) ) @@ -1711,9 +1708,17 @@ module Array { output = "ReturnValue.Element[?].Element[?]" or exists(ArrayIndex i, ArrayIndex j | - input = "Argument[self].Element[" + j + "].Element[" + i + "]" and + input = "Argument[self].Element[" + j + "!].Element[" + i + "!]" and output = "ReturnValue.Element[" + i + "].Element[" + j + "]" ) + or + exists(ArrayIndex i | + input = "Argument[self].Element[" + i + "!].Element[?]" and + output = "ReturnValue.Element[?].Element[" + i + "]" + or + input = "Argument[self].Element[?].Element[" + i + "!]" and + output = "ReturnValue.Element[" + i + "].Element[?]" + ) ) } } @@ -1863,13 +1868,13 @@ module Enumerable { CompactSummary() { this = "compact" } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].Element[?,0..]" and + input = "Argument[self].Element[0..]" and output = "ReturnValue.Element[?]" and preservesValue = true or exists(ConstantValue index | not index.isInt(_) and - input = "Argument[self].WithElement[" + index.serialize() + "]" and + input = "Argument[self].WithElement[" + index.serialize() + "!]" and output = "ReturnValue" and preservesValue = true ) @@ -1935,7 +1940,7 @@ module Enumerable { output = "ReturnValue.Element[?]" or exists(ArrayIndex j | - input = "Argument[self].Element[" + j + "]" and + input = "Argument[self].Element[" + j + "!]" and output = "ReturnValue.Element[" + (j - i) + "]" ) ) and @@ -2069,7 +2074,7 @@ module Enumerable { FirstNoArgSummary() { this = "first(no_arg)" and mc.getNumberOfArguments() = 0 } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = ["Argument[self].Element[0]", "Argument[self].Element[?]"] and + input = "Argument[self].Element[0]" and output = "ReturnValue" and preservesValue = true } @@ -2086,12 +2091,12 @@ module Enumerable { ( exists(ArrayIndex i | i < n and - input = "Argument[self].WithElement[" + i + "]" and + input = "Argument[self].WithElement[" + i + "!]" and output = "ReturnValue" ) or - input = "Argument[self].Element[?]" and - output = "ReturnValue.Element[?]" + input = "Argument[self].WithElement[?]" and + output = "ReturnValue" ) and preservesValue = true } @@ -2413,10 +2418,10 @@ module Enumerable { override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { ( // array indices may get shifted - input = "Argument[self].Element[0..]" and + input = "Argument[self].Element[0..!]" and output = "ReturnValue.Element[?]" or - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = "ReturnValue" or input = "Argument[self].Element[any]" and @@ -2442,10 +2447,10 @@ module Enumerable { override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { ( // array indices may get shifted - input = "Argument[self].Element[0..]" and + input = "Argument[self].Element[0..!]" and output = "ReturnValue.Element[?]" or - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = "ReturnValue" or input = "Argument[self].Element[any]" and @@ -2525,11 +2530,11 @@ module Enumerable { override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { ( - input = "Argument[self].Element[?]" and - output = "ReturnValue.Element[?]" + input = "Argument[self].WithElement[?]" and + output = "ReturnValue" or exists(ArrayIndex j | j < i | - input = "Argument[self].WithElement[" + j + "]" and + input = "Argument[self].WithElement[" + j + "!]" and output = "ReturnValue" ) ) and @@ -2576,7 +2581,7 @@ module Enumerable { ToASummary() { this = ["to_a", "entries", "to_ary"] } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].WithElement[?,0..]" and + input = "Argument[self].WithElement[0..]" and output = "ReturnValue" and preservesValue = true } @@ -2625,7 +2630,7 @@ module Enumerable { ( // receiver[i] -> return_value[i][0] exists(ArrayIndex i | - input = "Argument[self].Element[" + i + "]" and + input = "Argument[self].Element[" + i + "!]" and output = "ReturnValue.Element[" + i + "].Element[0]" ) or @@ -2635,7 +2640,7 @@ module Enumerable { or // arg_j[i] -> return_value[i][j+1] exists(ArrayIndex i, int j | j in [0 .. (mc.getNumberOfArguments() - 1)] | - input = "Argument[" + j + "].Element[" + i + "]" and + input = "Argument[" + j + "].Element[" + i + "!]" and output = "ReturnValue.Element[" + i + "].Element[" + (j + 1) + "]" ) or diff --git a/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll b/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll index cf0872e770e..f20e9f7be6d 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll @@ -176,7 +176,7 @@ module Hash { output = "Argument[self].Element[" + key.serialize() + "]" and preservesValue = true or - input = "Argument[self].WithoutElement[" + key.serialize() + "]" and + input = "Argument[self].WithoutElement[" + key.serialize() + "!]" and output = "Argument[self]" and preservesValue = true } @@ -217,7 +217,7 @@ module Hash { } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].Element[" + key.serialize() + ",?]" and + input = "Argument[self].Element[" + key.serialize() + "]" and output = "ReturnValue.Element[1]" and preservesValue = true } @@ -290,7 +290,7 @@ module Hash { concat(int i, string s | s = getExceptComponent(mc, i) | - ".WithoutElement[" + s + "]" order by i + ".WithoutElement[" + s + "!]" order by i ) and output = "ReturnValue" and preservesValue = true @@ -413,7 +413,7 @@ private class SliceKnownSummary extends SliceSummary { } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].WithElement[?," + key.serialize() + "]" and + input = "Argument[self].WithElement[" + key.serialize() + "]" and output = "ReturnValue" and preservesValue = true } @@ -426,7 +426,7 @@ private class SliceUnknownSummary extends SliceSummary { } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].WithoutElement[0..].WithElement[any]" and + input = "Argument[self].WithoutElement[0..!].WithElement[any]" and output = "ReturnValue" and preservesValue = true } @@ -436,7 +436,7 @@ private class ToASummary extends SimpleSummarizedCallable { ToASummary() { this = "to_a" } override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].WithoutElement[0..].Element[any]" and + input = "Argument[self].WithoutElement[0..!].Element[any]" and output = "ReturnValue.Element[?].Element[1]" and preservesValue = true } @@ -534,18 +534,3 @@ private class ValuesSummary extends SimpleSummarizedCallable { preservesValue = true } } - -abstract private class ValuesAtSummary extends SummarizedCallable { - MethodCall mc; - - bindingset[this] - ValuesAtSummary() { mc.getMethodName() = "values_at" } - - final override MethodCall getACall() { result = mc } - - override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { - input = "Argument[self].WithElement[?]" and - output = "ReturnValue" and - preservesValue = true - } -} diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected index ec6bf2843f9..2ac85200261 100644 --- a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected @@ -3381,14 +3381,8 @@ edges | array_flow.rb:1611:10:1611:13 | ...[...] [element 0] : | array_flow.rb:1611:10:1611:16 | ...[...] | | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | -| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1614:10:1614:10 | a [element, element 0] : | -| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1614:10:1614:10 | a [element, element 0] : | -| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1615:10:1615:10 | a [element, element 0] : | -| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | array_flow.rb:1615:10:1615:10 | a [element, element 0] : | | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | -| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | -| array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | | array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | | array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | | array_flow.rb:1614:10:1614:10 | a [element 1, element 0] : | array_flow.rb:1614:10:1614:13 | ...[...] [element 0] : | @@ -7038,8 +7032,6 @@ nodes | array_flow.rb:1611:10:1611:16 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | semmle.label | [post] a [element 1, element 0] : | | array_flow.rb:1613:5:1613:5 | [post] a [element 1, element 0] : | semmle.label | [post] a [element 1, element 0] : | -| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | semmle.label | [post] a [element, element 0] : | -| array_flow.rb:1613:5:1613:5 | [post] a [element, element 0] : | semmle.label | [post] a [element, element 0] : | | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | semmle.label | [post] ...[...] [element 0] : | | array_flow.rb:1613:5:1613:8 | [post] ...[...] [element 0] : | semmle.label | [post] ...[...] [element 0] : | | array_flow.rb:1613:15:1613:27 | call to source : | semmle.label | call to source : | @@ -7745,4 +7737,3 @@ subpaths | array_flow.rb:1614:10:1614:16 | ...[...] | array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1614:10:1614:16 | ...[...] | $@ | array_flow.rb:1610:15:1610:27 | call to source : | call to source : | | array_flow.rb:1614:10:1614:16 | ...[...] | array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1614:10:1614:16 | ...[...] | $@ | array_flow.rb:1613:15:1613:27 | call to source : | call to source : | | array_flow.rb:1615:10:1615:16 | ...[...] | array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1615:10:1615:16 | ...[...] | $@ | array_flow.rb:1610:15:1610:27 | call to source : | call to source : | -| array_flow.rb:1615:10:1615:16 | ...[...] | array_flow.rb:1613:15:1613:27 | call to source : | array_flow.rb:1615:10:1615:16 | ...[...] | $@ | array_flow.rb:1613:15:1613:27 | call to source : | call to source : | diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb b/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb index aa10ce09fae..e8838b980e6 100644 --- a/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb +++ b/ruby/ql/test/library-tests/dataflow/array-flow/array_flow.rb @@ -1612,5 +1612,5 @@ def m136(i) sink(a[0][1]) a[1][0] = source(136.2) sink(a[1][0]) # $ hasValueFlow=136.2 $ SPURIOUS hasValueFlow=136.1 - sink(a[2][0]) # $ hasValueFlow=136.1 $ SPURIOUS hasValueFlow=136.2 + sink(a[2][0]) # $ hasValueFlow=136.1 end From 31806b84ba7269be6b12a887c35830f58976a28e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 26 Sep 2022 14:52:38 +0200 Subject: [PATCH 3/4] Ruby: Add more flow summaries tests The tests highlight the differences between `(With|Without)?Element[1]` and `(With|Without)?Element[1!]`. --- .../dataflow/summaries/Summaries.expected | 400 +++++++++++++----- .../dataflow/summaries/Summaries.ql | 4 + .../dataflow/summaries/summaries.rb | 23 +- 3 files changed, 305 insertions(+), 122 deletions(-) diff --git a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected index 43b76952015..bf5cf7ff6ca 100644 --- a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected +++ b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected @@ -24,16 +24,16 @@ edges | summaries.rb:1:11:1:36 | call to identity : | summaries.rb:59:27:59:33 | tainted : | | summaries.rb:1:11:1:36 | call to identity : | summaries.rb:63:32:63:38 | tainted : | | summaries.rb:1:11:1:36 | call to identity : | summaries.rb:65:23:65:29 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:104:16:104:22 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:110:14:110:20 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:113:16:113:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:113:16:113:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:114:21:114:27 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:114:21:114:27 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:117:26:117:32 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:117:26:117:32 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:119:23:119:29 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:119:23:119:29 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:115:16:115:22 | tainted : | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:121:14:121:20 | tainted : | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:124:16:124:22 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:124:16:124:22 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:125:21:125:27 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:125:21:125:27 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:128:26:128:32 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:128:26:128:32 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:130:23:130:29 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:130:23:130:29 | tainted | | summaries.rb:1:20:1:36 | call to source : | summaries.rb:1:11:1:36 | call to identity : | | summaries.rb:1:20:1:36 | call to source : | summaries.rb:1:11:1:36 | call to identity : | | summaries.rb:4:12:7:3 | call to apply_block : | summaries.rb:9:6:9:13 | tainted2 | @@ -79,46 +79,120 @@ edges | summaries.rb:76:26:76:56 | call to source : | summaries.rb:76:8:76:57 | call to preserveTaint | | summaries.rb:79:15:79:29 | call to source : | summaries.rb:81:6:81:6 | a [element 1] : | | summaries.rb:79:15:79:29 | call to source : | summaries.rb:81:6:81:6 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:83:5:83:5 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:83:5:83:5 | a [element 1] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:82:6:82:6 | a [element 2] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:82:6:82:6 | a [element 2] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:87:1:87:1 | a [element 2] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:87:1:87:1 | a [element 2] : | -| summaries.rb:81:6:81:6 | a [element 1] : | summaries.rb:81:6:81:9 | ...[...] | -| summaries.rb:81:6:81:6 | a [element 1] : | summaries.rb:81:6:81:9 | ...[...] | -| summaries.rb:82:6:82:6 | a [element 2] : | summaries.rb:82:6:82:9 | ...[...] | -| summaries.rb:82:6:82:6 | a [element 2] : | summaries.rb:82:6:82:9 | ...[...] | -| summaries.rb:83:5:83:5 | a [element 1] : | summaries.rb:83:5:83:22 | call to withElementOne [element 1] : | -| summaries.rb:83:5:83:5 | a [element 1] : | summaries.rb:83:5:83:22 | call to withElementOne [element 1] : | -| summaries.rb:83:5:83:22 | call to withElementOne [element 1] : | summaries.rb:85:6:85:6 | b [element 1] : | -| summaries.rb:83:5:83:22 | call to withElementOne [element 1] : | summaries.rb:85:6:85:6 | b [element 1] : | -| summaries.rb:85:6:85:6 | b [element 1] : | summaries.rb:85:6:85:9 | ...[...] | -| summaries.rb:85:6:85:6 | b [element 1] : | summaries.rb:85:6:85:9 | ...[...] | -| summaries.rb:87:1:87:1 | [post] a [element 2] : | summaries.rb:90:6:90:6 | a [element 2] : | -| summaries.rb:87:1:87:1 | [post] a [element 2] : | summaries.rb:90:6:90:6 | a [element 2] : | -| summaries.rb:87:1:87:1 | a [element 2] : | summaries.rb:87:1:87:1 | [post] a [element 2] : | -| summaries.rb:87:1:87:1 | a [element 2] : | summaries.rb:87:1:87:1 | [post] a [element 2] : | -| summaries.rb:90:6:90:6 | a [element 2] : | summaries.rb:90:6:90:9 | ...[...] | -| summaries.rb:90:6:90:6 | a [element 2] : | summaries.rb:90:6:90:9 | ...[...] | -| summaries.rb:93:1:93:1 | [post] x [@value] : | summaries.rb:94:6:94:6 | x [@value] : | -| summaries.rb:93:1:93:1 | [post] x [@value] : | summaries.rb:94:6:94:6 | x [@value] : | -| summaries.rb:93:13:93:26 | call to source : | summaries.rb:93:1:93:1 | [post] x [@value] : | -| summaries.rb:93:13:93:26 | call to source : | summaries.rb:93:1:93:1 | [post] x [@value] : | -| summaries.rb:94:6:94:6 | x [@value] : | summaries.rb:94:6:94:16 | call to get_value | -| summaries.rb:94:6:94:6 | x [@value] : | summaries.rb:94:6:94:16 | call to get_value | -| summaries.rb:104:16:104:22 | [post] tainted : | summaries.rb:110:14:110:20 | tainted : | -| summaries.rb:104:16:104:22 | [post] tainted : | summaries.rb:113:16:113:22 | tainted | -| summaries.rb:104:16:104:22 | [post] tainted : | summaries.rb:114:21:114:27 | tainted | -| summaries.rb:104:16:104:22 | [post] tainted : | summaries.rb:117:26:117:32 | tainted | -| summaries.rb:104:16:104:22 | [post] tainted : | summaries.rb:119:23:119:29 | tainted | -| summaries.rb:104:16:104:22 | tainted : | summaries.rb:104:16:104:22 | [post] tainted : | -| summaries.rb:104:16:104:22 | tainted : | summaries.rb:104:25:104:25 | [post] y : | -| summaries.rb:104:16:104:22 | tainted : | summaries.rb:104:33:104:33 | [post] z : | -| summaries.rb:104:25:104:25 | [post] y : | summaries.rb:106:6:106:6 | y | -| summaries.rb:104:33:104:33 | [post] z : | summaries.rb:107:6:107:6 | z | -| summaries.rb:110:1:110:1 | [post] x : | summaries.rb:111:6:111:6 | x | -| summaries.rb:110:14:110:20 | tainted : | summaries.rb:110:1:110:1 | [post] x : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:82:6:82:6 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:82:6:82:6 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:84:6:84:6 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:84:6:84:6 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:86:5:86:5 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:86:5:86:5 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:90:5:90:5 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:90:5:90:5 | a [element 1] : | +| summaries.rb:79:32:79:46 | call to source : | summaries.rb:85:6:85:6 | a [element 2] : | +| summaries.rb:79:32:79:46 | call to source : | summaries.rb:85:6:85:6 | a [element 2] : | +| summaries.rb:79:32:79:46 | call to source : | summaries.rb:94:1:94:1 | a [element 2] : | +| summaries.rb:79:32:79:46 | call to source : | summaries.rb:94:1:94:1 | a [element 2] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:81:6:81:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:81:6:81:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:83:6:83:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:83:6:83:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:84:6:84:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:84:6:84:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:85:6:85:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:85:6:85:6 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:86:5:86:5 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:86:5:86:5 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:94:1:94:1 | a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | summaries.rb:94:1:94:1 | a [element] : | +| summaries.rb:80:13:80:27 | call to source : | summaries.rb:80:1:80:1 | [post] a [element] : | +| summaries.rb:80:13:80:27 | call to source : | summaries.rb:80:1:80:1 | [post] a [element] : | +| summaries.rb:81:6:81:6 | a [element 1] : | summaries.rb:81:6:81:24 | call to readElementOne | +| summaries.rb:81:6:81:6 | a [element 1] : | summaries.rb:81:6:81:24 | call to readElementOne | +| summaries.rb:81:6:81:6 | a [element] : | summaries.rb:81:6:81:24 | call to readElementOne | +| summaries.rb:81:6:81:6 | a [element] : | summaries.rb:81:6:81:24 | call to readElementOne | +| summaries.rb:82:6:82:6 | a [element 1] : | summaries.rb:82:6:82:31 | call to readExactlyElementOne | +| summaries.rb:82:6:82:6 | a [element 1] : | summaries.rb:82:6:82:31 | call to readExactlyElementOne | +| summaries.rb:83:6:83:6 | a [element] : | summaries.rb:83:6:83:9 | ...[...] | +| summaries.rb:83:6:83:6 | a [element] : | summaries.rb:83:6:83:9 | ...[...] | +| summaries.rb:84:6:84:6 | a [element 1] : | summaries.rb:84:6:84:9 | ...[...] | +| summaries.rb:84:6:84:6 | a [element 1] : | summaries.rb:84:6:84:9 | ...[...] | +| summaries.rb:84:6:84:6 | a [element] : | summaries.rb:84:6:84:9 | ...[...] | +| summaries.rb:84:6:84:6 | a [element] : | summaries.rb:84:6:84:9 | ...[...] | +| summaries.rb:85:6:85:6 | a [element 2] : | summaries.rb:85:6:85:9 | ...[...] | +| summaries.rb:85:6:85:6 | a [element 2] : | summaries.rb:85:6:85:9 | ...[...] | +| summaries.rb:85:6:85:6 | a [element] : | summaries.rb:85:6:85:9 | ...[...] | +| summaries.rb:85:6:85:6 | a [element] : | summaries.rb:85:6:85:9 | ...[...] | +| summaries.rb:86:5:86:5 | a [element 1] : | summaries.rb:86:5:86:22 | call to withElementOne [element 1] : | +| summaries.rb:86:5:86:5 | a [element 1] : | summaries.rb:86:5:86:22 | call to withElementOne [element 1] : | +| summaries.rb:86:5:86:5 | a [element] : | summaries.rb:86:5:86:22 | call to withElementOne [element] : | +| summaries.rb:86:5:86:5 | a [element] : | summaries.rb:86:5:86:22 | call to withElementOne [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element 1] : | summaries.rb:88:6:88:6 | b [element 1] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element 1] : | summaries.rb:88:6:88:6 | b [element 1] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | summaries.rb:87:6:87:6 | b [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | summaries.rb:87:6:87:6 | b [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | summaries.rb:88:6:88:6 | b [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | summaries.rb:88:6:88:6 | b [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | summaries.rb:89:6:89:6 | b [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | summaries.rb:89:6:89:6 | b [element] : | +| summaries.rb:87:6:87:6 | b [element] : | summaries.rb:87:6:87:9 | ...[...] | +| summaries.rb:87:6:87:6 | b [element] : | summaries.rb:87:6:87:9 | ...[...] | +| summaries.rb:88:6:88:6 | b [element 1] : | summaries.rb:88:6:88:9 | ...[...] | +| summaries.rb:88:6:88:6 | b [element 1] : | summaries.rb:88:6:88:9 | ...[...] | +| summaries.rb:88:6:88:6 | b [element] : | summaries.rb:88:6:88:9 | ...[...] | +| summaries.rb:88:6:88:6 | b [element] : | summaries.rb:88:6:88:9 | ...[...] | +| summaries.rb:89:6:89:6 | b [element] : | summaries.rb:89:6:89:9 | ...[...] | +| summaries.rb:89:6:89:6 | b [element] : | summaries.rb:89:6:89:9 | ...[...] | +| summaries.rb:90:5:90:5 | a [element 1] : | summaries.rb:90:5:90:29 | call to withExactlyElementOne [element 1] : | +| summaries.rb:90:5:90:5 | a [element 1] : | summaries.rb:90:5:90:29 | call to withExactlyElementOne [element 1] : | +| summaries.rb:90:5:90:29 | call to withExactlyElementOne [element 1] : | summaries.rb:92:6:92:6 | c [element 1] : | +| summaries.rb:90:5:90:29 | call to withExactlyElementOne [element 1] : | summaries.rb:92:6:92:6 | c [element 1] : | +| summaries.rb:92:6:92:6 | c [element 1] : | summaries.rb:92:6:92:9 | ...[...] | +| summaries.rb:92:6:92:6 | c [element 1] : | summaries.rb:92:6:92:9 | ...[...] | +| summaries.rb:94:1:94:1 | [post] a [element 2] : | summaries.rb:97:6:97:6 | a [element 2] : | +| summaries.rb:94:1:94:1 | [post] a [element 2] : | summaries.rb:97:6:97:6 | a [element 2] : | +| summaries.rb:94:1:94:1 | [post] a [element 2] : | summaries.rb:98:1:98:1 | a [element 2] : | +| summaries.rb:94:1:94:1 | [post] a [element 2] : | summaries.rb:98:1:98:1 | a [element 2] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | summaries.rb:95:6:95:6 | a [element] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | summaries.rb:95:6:95:6 | a [element] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | summaries.rb:96:6:96:6 | a [element] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | summaries.rb:96:6:96:6 | a [element] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | summaries.rb:97:6:97:6 | a [element] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | summaries.rb:97:6:97:6 | a [element] : | +| summaries.rb:94:1:94:1 | a [element 2] : | summaries.rb:94:1:94:1 | [post] a [element 2] : | +| summaries.rb:94:1:94:1 | a [element 2] : | summaries.rb:94:1:94:1 | [post] a [element 2] : | +| summaries.rb:94:1:94:1 | a [element] : | summaries.rb:94:1:94:1 | [post] a [element] : | +| summaries.rb:94:1:94:1 | a [element] : | summaries.rb:94:1:94:1 | [post] a [element] : | +| summaries.rb:95:6:95:6 | a [element] : | summaries.rb:95:6:95:9 | ...[...] | +| summaries.rb:95:6:95:6 | a [element] : | summaries.rb:95:6:95:9 | ...[...] | +| summaries.rb:96:6:96:6 | a [element] : | summaries.rb:96:6:96:9 | ...[...] | +| summaries.rb:96:6:96:6 | a [element] : | summaries.rb:96:6:96:9 | ...[...] | +| summaries.rb:97:6:97:6 | a [element 2] : | summaries.rb:97:6:97:9 | ...[...] | +| summaries.rb:97:6:97:6 | a [element 2] : | summaries.rb:97:6:97:9 | ...[...] | +| summaries.rb:97:6:97:6 | a [element] : | summaries.rb:97:6:97:9 | ...[...] | +| summaries.rb:97:6:97:6 | a [element] : | summaries.rb:97:6:97:9 | ...[...] | +| summaries.rb:98:1:98:1 | [post] a [element 2] : | summaries.rb:101:6:101:6 | a [element 2] : | +| summaries.rb:98:1:98:1 | [post] a [element 2] : | summaries.rb:101:6:101:6 | a [element 2] : | +| summaries.rb:98:1:98:1 | a [element 2] : | summaries.rb:98:1:98:1 | [post] a [element 2] : | +| summaries.rb:98:1:98:1 | a [element 2] : | summaries.rb:98:1:98:1 | [post] a [element 2] : | +| summaries.rb:101:6:101:6 | a [element 2] : | summaries.rb:101:6:101:9 | ...[...] | +| summaries.rb:101:6:101:6 | a [element 2] : | summaries.rb:101:6:101:9 | ...[...] | +| summaries.rb:104:1:104:1 | [post] x [@value] : | summaries.rb:105:6:105:6 | x [@value] : | +| summaries.rb:104:1:104:1 | [post] x [@value] : | summaries.rb:105:6:105:6 | x [@value] : | +| summaries.rb:104:13:104:26 | call to source : | summaries.rb:104:1:104:1 | [post] x [@value] : | +| summaries.rb:104:13:104:26 | call to source : | summaries.rb:104:1:104:1 | [post] x [@value] : | +| summaries.rb:105:6:105:6 | x [@value] : | summaries.rb:105:6:105:16 | call to get_value | +| summaries.rb:105:6:105:6 | x [@value] : | summaries.rb:105:6:105:16 | call to get_value | +| summaries.rb:115:16:115:22 | [post] tainted : | summaries.rb:121:14:121:20 | tainted : | +| summaries.rb:115:16:115:22 | [post] tainted : | summaries.rb:124:16:124:22 | tainted | +| summaries.rb:115:16:115:22 | [post] tainted : | summaries.rb:125:21:125:27 | tainted | +| summaries.rb:115:16:115:22 | [post] tainted : | summaries.rb:128:26:128:32 | tainted | +| summaries.rb:115:16:115:22 | [post] tainted : | summaries.rb:130:23:130:29 | tainted | +| summaries.rb:115:16:115:22 | tainted : | summaries.rb:115:16:115:22 | [post] tainted : | +| summaries.rb:115:16:115:22 | tainted : | summaries.rb:115:25:115:25 | [post] y : | +| summaries.rb:115:16:115:22 | tainted : | summaries.rb:115:33:115:33 | [post] z : | +| summaries.rb:115:25:115:25 | [post] y : | summaries.rb:117:6:117:6 | y | +| summaries.rb:115:33:115:33 | [post] z : | summaries.rb:118:6:118:6 | z | +| summaries.rb:121:1:121:1 | [post] x : | summaries.rb:122:6:122:6 | x | +| summaries.rb:121:14:121:20 | tainted : | summaries.rb:121:1:121:1 | [post] x : | nodes | summaries.rb:1:11:1:36 | call to identity : | semmle.label | call to identity : | | summaries.rb:1:11:1:36 | call to identity : | semmle.label | call to identity : | @@ -198,55 +272,121 @@ nodes | summaries.rb:79:15:79:29 | call to source : | semmle.label | call to source : | | summaries.rb:79:32:79:46 | call to source : | semmle.label | call to source : | | summaries.rb:79:32:79:46 | call to source : | semmle.label | call to source : | +| summaries.rb:80:1:80:1 | [post] a [element] : | semmle.label | [post] a [element] : | +| summaries.rb:80:1:80:1 | [post] a [element] : | semmle.label | [post] a [element] : | +| summaries.rb:80:13:80:27 | call to source : | semmle.label | call to source : | +| summaries.rb:80:13:80:27 | call to source : | semmle.label | call to source : | | summaries.rb:81:6:81:6 | a [element 1] : | semmle.label | a [element 1] : | | summaries.rb:81:6:81:6 | a [element 1] : | semmle.label | a [element 1] : | -| summaries.rb:81:6:81:9 | ...[...] | semmle.label | ...[...] | -| summaries.rb:81:6:81:9 | ...[...] | semmle.label | ...[...] | -| summaries.rb:82:6:82:6 | a [element 2] : | semmle.label | a [element 2] : | -| summaries.rb:82:6:82:6 | a [element 2] : | semmle.label | a [element 2] : | -| summaries.rb:82:6:82:9 | ...[...] | semmle.label | ...[...] | -| summaries.rb:82:6:82:9 | ...[...] | semmle.label | ...[...] | -| summaries.rb:83:5:83:5 | a [element 1] : | semmle.label | a [element 1] : | -| summaries.rb:83:5:83:5 | a [element 1] : | semmle.label | a [element 1] : | -| summaries.rb:83:5:83:22 | call to withElementOne [element 1] : | semmle.label | call to withElementOne [element 1] : | -| summaries.rb:83:5:83:22 | call to withElementOne [element 1] : | semmle.label | call to withElementOne [element 1] : | -| summaries.rb:85:6:85:6 | b [element 1] : | semmle.label | b [element 1] : | -| summaries.rb:85:6:85:6 | b [element 1] : | semmle.label | b [element 1] : | +| summaries.rb:81:6:81:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:81:6:81:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:81:6:81:24 | call to readElementOne | semmle.label | call to readElementOne | +| summaries.rb:81:6:81:24 | call to readElementOne | semmle.label | call to readElementOne | +| summaries.rb:82:6:82:6 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:82:6:82:6 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:82:6:82:31 | call to readExactlyElementOne | semmle.label | call to readExactlyElementOne | +| summaries.rb:82:6:82:31 | call to readExactlyElementOne | semmle.label | call to readExactlyElementOne | +| summaries.rb:83:6:83:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:83:6:83:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:83:6:83:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:83:6:83:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:84:6:84:6 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:84:6:84:6 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:84:6:84:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:84:6:84:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:84:6:84:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:84:6:84:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:85:6:85:6 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:85:6:85:6 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:85:6:85:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:85:6:85:6 | a [element] : | semmle.label | a [element] : | | summaries.rb:85:6:85:9 | ...[...] | semmle.label | ...[...] | | summaries.rb:85:6:85:9 | ...[...] | semmle.label | ...[...] | -| summaries.rb:87:1:87:1 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | -| summaries.rb:87:1:87:1 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | -| summaries.rb:87:1:87:1 | a [element 2] : | semmle.label | a [element 2] : | -| summaries.rb:87:1:87:1 | a [element 2] : | semmle.label | a [element 2] : | -| summaries.rb:90:6:90:6 | a [element 2] : | semmle.label | a [element 2] : | -| summaries.rb:90:6:90:6 | a [element 2] : | semmle.label | a [element 2] : | -| summaries.rb:90:6:90:9 | ...[...] | semmle.label | ...[...] | -| summaries.rb:90:6:90:9 | ...[...] | semmle.label | ...[...] | -| summaries.rb:93:1:93:1 | [post] x [@value] : | semmle.label | [post] x [@value] : | -| summaries.rb:93:1:93:1 | [post] x [@value] : | semmle.label | [post] x [@value] : | -| summaries.rb:93:13:93:26 | call to source : | semmle.label | call to source : | -| summaries.rb:93:13:93:26 | call to source : | semmle.label | call to source : | -| summaries.rb:94:6:94:6 | x [@value] : | semmle.label | x [@value] : | -| summaries.rb:94:6:94:6 | x [@value] : | semmle.label | x [@value] : | -| summaries.rb:94:6:94:16 | call to get_value | semmle.label | call to get_value | -| summaries.rb:94:6:94:16 | call to get_value | semmle.label | call to get_value | -| summaries.rb:104:16:104:22 | [post] tainted : | semmle.label | [post] tainted : | -| summaries.rb:104:16:104:22 | tainted : | semmle.label | tainted : | -| summaries.rb:104:25:104:25 | [post] y : | semmle.label | [post] y : | -| summaries.rb:104:33:104:33 | [post] z : | semmle.label | [post] z : | -| summaries.rb:106:6:106:6 | y | semmle.label | y | -| summaries.rb:107:6:107:6 | z | semmle.label | z | -| summaries.rb:110:1:110:1 | [post] x : | semmle.label | [post] x : | -| summaries.rb:110:14:110:20 | tainted : | semmle.label | tainted : | -| summaries.rb:111:6:111:6 | x | semmle.label | x | -| summaries.rb:113:16:113:22 | tainted | semmle.label | tainted | -| summaries.rb:113:16:113:22 | tainted | semmle.label | tainted | -| summaries.rb:114:21:114:27 | tainted | semmle.label | tainted | -| summaries.rb:114:21:114:27 | tainted | semmle.label | tainted | -| summaries.rb:117:26:117:32 | tainted | semmle.label | tainted | -| summaries.rb:117:26:117:32 | tainted | semmle.label | tainted | -| summaries.rb:119:23:119:29 | tainted | semmle.label | tainted | -| summaries.rb:119:23:119:29 | tainted | semmle.label | tainted | +| summaries.rb:86:5:86:5 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:86:5:86:5 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:86:5:86:5 | a [element] : | semmle.label | a [element] : | +| summaries.rb:86:5:86:5 | a [element] : | semmle.label | a [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element 1] : | semmle.label | call to withElementOne [element 1] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element 1] : | semmle.label | call to withElementOne [element 1] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | semmle.label | call to withElementOne [element] : | +| summaries.rb:86:5:86:22 | call to withElementOne [element] : | semmle.label | call to withElementOne [element] : | +| summaries.rb:87:6:87:6 | b [element] : | semmle.label | b [element] : | +| summaries.rb:87:6:87:6 | b [element] : | semmle.label | b [element] : | +| summaries.rb:87:6:87:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:87:6:87:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:88:6:88:6 | b [element 1] : | semmle.label | b [element 1] : | +| summaries.rb:88:6:88:6 | b [element 1] : | semmle.label | b [element 1] : | +| summaries.rb:88:6:88:6 | b [element] : | semmle.label | b [element] : | +| summaries.rb:88:6:88:6 | b [element] : | semmle.label | b [element] : | +| summaries.rb:88:6:88:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:88:6:88:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:89:6:89:6 | b [element] : | semmle.label | b [element] : | +| summaries.rb:89:6:89:6 | b [element] : | semmle.label | b [element] : | +| summaries.rb:89:6:89:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:89:6:89:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:90:5:90:5 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:90:5:90:5 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:90:5:90:29 | call to withExactlyElementOne [element 1] : | semmle.label | call to withExactlyElementOne [element 1] : | +| summaries.rb:90:5:90:29 | call to withExactlyElementOne [element 1] : | semmle.label | call to withExactlyElementOne [element 1] : | +| summaries.rb:92:6:92:6 | c [element 1] : | semmle.label | c [element 1] : | +| summaries.rb:92:6:92:6 | c [element 1] : | semmle.label | c [element 1] : | +| summaries.rb:92:6:92:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:92:6:92:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:94:1:94:1 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | +| summaries.rb:94:1:94:1 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | semmle.label | [post] a [element] : | +| summaries.rb:94:1:94:1 | [post] a [element] : | semmle.label | [post] a [element] : | +| summaries.rb:94:1:94:1 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:94:1:94:1 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:94:1:94:1 | a [element] : | semmle.label | a [element] : | +| summaries.rb:94:1:94:1 | a [element] : | semmle.label | a [element] : | +| summaries.rb:95:6:95:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:95:6:95:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:95:6:95:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:95:6:95:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:96:6:96:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:96:6:96:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:96:6:96:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:96:6:96:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:97:6:97:6 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:97:6:97:6 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:97:6:97:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:97:6:97:6 | a [element] : | semmle.label | a [element] : | +| summaries.rb:97:6:97:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:97:6:97:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:98:1:98:1 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | +| summaries.rb:98:1:98:1 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | +| summaries.rb:98:1:98:1 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:98:1:98:1 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:101:6:101:6 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:101:6:101:6 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:101:6:101:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:101:6:101:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:104:1:104:1 | [post] x [@value] : | semmle.label | [post] x [@value] : | +| summaries.rb:104:1:104:1 | [post] x [@value] : | semmle.label | [post] x [@value] : | +| summaries.rb:104:13:104:26 | call to source : | semmle.label | call to source : | +| summaries.rb:104:13:104:26 | call to source : | semmle.label | call to source : | +| summaries.rb:105:6:105:6 | x [@value] : | semmle.label | x [@value] : | +| summaries.rb:105:6:105:6 | x [@value] : | semmle.label | x [@value] : | +| summaries.rb:105:6:105:16 | call to get_value | semmle.label | call to get_value | +| summaries.rb:105:6:105:16 | call to get_value | semmle.label | call to get_value | +| summaries.rb:115:16:115:22 | [post] tainted : | semmle.label | [post] tainted : | +| summaries.rb:115:16:115:22 | tainted : | semmle.label | tainted : | +| summaries.rb:115:25:115:25 | [post] y : | semmle.label | [post] y : | +| summaries.rb:115:33:115:33 | [post] z : | semmle.label | [post] z : | +| summaries.rb:117:6:117:6 | y | semmle.label | y | +| summaries.rb:118:6:118:6 | z | semmle.label | z | +| summaries.rb:121:1:121:1 | [post] x : | semmle.label | [post] x : | +| summaries.rb:121:14:121:20 | tainted : | semmle.label | tainted : | +| summaries.rb:122:6:122:6 | x | semmle.label | x | +| summaries.rb:124:16:124:22 | tainted | semmle.label | tainted | +| summaries.rb:124:16:124:22 | tainted | semmle.label | tainted | +| summaries.rb:125:21:125:27 | tainted | semmle.label | tainted | +| summaries.rb:125:21:125:27 | tainted | semmle.label | tainted | +| summaries.rb:128:26:128:32 | tainted | semmle.label | tainted | +| summaries.rb:128:26:128:32 | tainted | semmle.label | tainted | +| summaries.rb:130:23:130:29 | tainted | semmle.label | tainted | +| summaries.rb:130:23:130:29 | tainted | semmle.label | tainted | subpaths invalidSpecComponent #select @@ -285,27 +425,55 @@ invalidSpecComponent | summaries.rb:66:8:66:8 | x | summaries.rb:1:20:1:36 | call to source : | summaries.rb:66:8:66:8 | x | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | | summaries.rb:73:8:73:54 | call to preserveTaint | summaries.rb:73:24:73:53 | call to source : | summaries.rb:73:8:73:54 | call to preserveTaint | $@ | summaries.rb:73:24:73:53 | call to source : | call to source : | | summaries.rb:76:8:76:57 | call to preserveTaint | summaries.rb:76:26:76:56 | call to source : | summaries.rb:76:8:76:57 | call to preserveTaint | $@ | summaries.rb:76:26:76:56 | call to source : | call to source : | -| summaries.rb:81:6:81:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:81:6:81:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | -| summaries.rb:81:6:81:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:81:6:81:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | -| summaries.rb:82:6:82:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:82:6:82:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | -| summaries.rb:82:6:82:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:82:6:82:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | -| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | -| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | -| summaries.rb:90:6:90:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:90:6:90:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | -| summaries.rb:90:6:90:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:90:6:90:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | -| summaries.rb:94:6:94:16 | call to get_value | summaries.rb:93:13:93:26 | call to source : | summaries.rb:94:6:94:16 | call to get_value | $@ | summaries.rb:93:13:93:26 | call to source : | call to source : | -| summaries.rb:94:6:94:16 | call to get_value | summaries.rb:93:13:93:26 | call to source : | summaries.rb:94:6:94:16 | call to get_value | $@ | summaries.rb:93:13:93:26 | call to source : | call to source : | -| summaries.rb:106:6:106:6 | y | summaries.rb:1:20:1:36 | call to source : | summaries.rb:106:6:106:6 | y | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:107:6:107:6 | z | summaries.rb:1:20:1:36 | call to source : | summaries.rb:107:6:107:6 | z | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:111:6:111:6 | x | summaries.rb:1:20:1:36 | call to source : | summaries.rb:111:6:111:6 | x | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:113:16:113:22 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:113:16:113:22 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:113:16:113:22 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:113:16:113:22 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:114:21:114:27 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:114:21:114:27 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:114:21:114:27 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:114:21:114:27 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:117:26:117:32 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:117:26:117:32 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:117:26:117:32 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:117:26:117:32 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:119:23:119:29 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:119:23:119:29 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | -| summaries.rb:119:23:119:29 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:119:23:119:29 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:81:6:81:24 | call to readElementOne | summaries.rb:79:15:79:29 | call to source : | summaries.rb:81:6:81:24 | call to readElementOne | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:81:6:81:24 | call to readElementOne | summaries.rb:79:15:79:29 | call to source : | summaries.rb:81:6:81:24 | call to readElementOne | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:81:6:81:24 | call to readElementOne | summaries.rb:80:13:80:27 | call to source : | summaries.rb:81:6:81:24 | call to readElementOne | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:81:6:81:24 | call to readElementOne | summaries.rb:80:13:80:27 | call to source : | summaries.rb:81:6:81:24 | call to readElementOne | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:82:6:82:31 | call to readExactlyElementOne | summaries.rb:79:15:79:29 | call to source : | summaries.rb:82:6:82:31 | call to readExactlyElementOne | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:82:6:82:31 | call to readExactlyElementOne | summaries.rb:79:15:79:29 | call to source : | summaries.rb:82:6:82:31 | call to readExactlyElementOne | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:83:6:83:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:83:6:83:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:83:6:83:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:83:6:83:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:84:6:84:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:84:6:84:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:84:6:84:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:84:6:84:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:84:6:84:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:84:6:84:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:84:6:84:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:84:6:84:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | +| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | +| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:87:6:87:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:87:6:87:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:87:6:87:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:87:6:87:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:88:6:88:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:88:6:88:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:88:6:88:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:88:6:88:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:88:6:88:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:88:6:88:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:88:6:88:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:88:6:88:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:89:6:89:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:89:6:89:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:89:6:89:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:89:6:89:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:92:6:92:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:92:6:92:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:92:6:92:9 | ...[...] | summaries.rb:79:15:79:29 | call to source : | summaries.rb:92:6:92:9 | ...[...] | $@ | summaries.rb:79:15:79:29 | call to source : | call to source : | +| summaries.rb:95:6:95:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:95:6:95:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:95:6:95:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:95:6:95:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:96:6:96:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:96:6:96:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:96:6:96:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:96:6:96:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:97:6:97:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:97:6:97:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | +| summaries.rb:97:6:97:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:97:6:97:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | +| summaries.rb:97:6:97:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:97:6:97:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:97:6:97:9 | ...[...] | summaries.rb:80:13:80:27 | call to source : | summaries.rb:97:6:97:9 | ...[...] | $@ | summaries.rb:80:13:80:27 | call to source : | call to source : | +| summaries.rb:101:6:101:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:101:6:101:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | +| summaries.rb:101:6:101:9 | ...[...] | summaries.rb:79:32:79:46 | call to source : | summaries.rb:101:6:101:9 | ...[...] | $@ | summaries.rb:79:32:79:46 | call to source : | call to source : | +| summaries.rb:105:6:105:16 | call to get_value | summaries.rb:104:13:104:26 | call to source : | summaries.rb:105:6:105:16 | call to get_value | $@ | summaries.rb:104:13:104:26 | call to source : | call to source : | +| summaries.rb:105:6:105:16 | call to get_value | summaries.rb:104:13:104:26 | call to source : | summaries.rb:105:6:105:16 | call to get_value | $@ | summaries.rb:104:13:104:26 | call to source : | call to source : | +| summaries.rb:117:6:117:6 | y | summaries.rb:1:20:1:36 | call to source : | summaries.rb:117:6:117:6 | y | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:118:6:118:6 | z | summaries.rb:1:20:1:36 | call to source : | summaries.rb:118:6:118:6 | z | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:122:6:122:6 | x | summaries.rb:1:20:1:36 | call to source : | summaries.rb:122:6:122:6 | x | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:124:16:124:22 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:124:16:124:22 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:124:16:124:22 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:124:16:124:22 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:125:21:125:27 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:125:21:125:27 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:125:21:125:27 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:125:21:125:27 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:128:26:128:32 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:128:26:128:32 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:128:26:128:32 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:128:26:128:32 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:130:23:130:29 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:130:23:130:29 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | +| summaries.rb:130:23:130:29 | tainted | summaries.rb:1:20:1:36 | call to source : | summaries.rb:130:23:130:29 | tainted | $@ | summaries.rb:1:20:1:36 | call to source : | call to source : | warning | CSV type row should have 5 columns but has 2: test;TooFewColumns | | CSV type row should have 5 columns but has 8: test;TooManyColumns;;;Member[Foo].Instance;too;many;columns | diff --git a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql index e682c120ca5..2ac0a98b35f 100644 --- a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql +++ b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql @@ -86,7 +86,11 @@ private class StepsFromModel extends ModelInput::SummaryModelCsv { ";any;Method[matchedByName];Argument[0];ReturnValue;taint", ";any;Method[matchedByNameRcv];Argument[self];ReturnValue;taint", ";any;Method[withElementOne];Argument[self].WithElement[1];ReturnValue;value", + ";any;Method[withExactlyElementOne];Argument[self].WithElement[1!];ReturnValue;value", ";any;Method[withoutElementOne];Argument[self].WithoutElement[1];Argument[self];value", + ";any;Method[withoutExactlyElementOne];Argument[self].WithoutElement[1!];Argument[self];value", + ";any;Method[readElementOne];Argument[self].Element[1];ReturnValue;value", + ";any;Method[readExactlyElementOne];Argument[self].Element[1!];ReturnValue;value" ] } } diff --git a/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb b/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb index 51587ab050d..bf80b13c78d 100644 --- a/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb +++ b/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb @@ -77,13 +77,24 @@ Foo.startInNamedParameter(->(foo:) { }) a = ["elem0", source("elem1"), source("elem2")] -sink(a[0]) -sink(a[1]) # $ hasValueFlow=elem1 -sink(a[2]) # $ hasValueFlow=elem2 +a[rand()] = source("elem3") +sink(a.readElementOne(1)) # $ hasValueFlow=elem1 $ hasValueFlow=elem3 +sink(a.readExactlyElementOne(1)) # $ hasValueFlow=elem1 +sink(a[0]) # $ hasValueFlow=elem3 +sink(a[1]) # $ hasValueFlow=elem1 $ hasValueFlow=elem3 +sink(a[2]) # $ hasValueFlow=elem2 $ hasValueFlow=elem3 b = a.withElementOne() -sink(b[0]) -sink(b[1]) # $ hasValueFlow=elem1 -sink(b[2]) +sink(b[0]) # $ hasValueFlow=elem3 +sink(b[1]) # $ hasValueFlow=elem1 $ hasValueFlow=elem3 +sink(b[2]) # $ hasValueFlow=elem3 +c = a.withExactlyElementOne() +sink(c[0]) +sink(c[1]) # $ hasValueFlow=elem1 +sink(c[2]) +a.withoutExactlyElementOne() +sink(a[0]) # $ hasValueFlow=elem3 +sink(a[1]) # $ hasValueFlow=elem3 +sink(a[2]) # $ hasValueFlow=elem2 $ hasValueFlow=elem3 a.withoutElementOne() sink(a[0]) sink(a[1]) From 92a38b30cf092347ff9ede1370b329a75594fa82 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 28 Sep 2022 09:32:52 +0200 Subject: [PATCH 4/4] Data flow: Update documentation on array flow modeling --- docs/ql-libraries/dataflow/dataflow.md | 47 +++++++++++++++----------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/docs/ql-libraries/dataflow/dataflow.md b/docs/ql-libraries/dataflow/dataflow.md index 5cbe00a087f..021c16a1536 100644 --- a/docs/ql-libraries/dataflow/dataflow.md +++ b/docs/ql-libraries/dataflow/dataflow.md @@ -419,6 +419,7 @@ class Content extends TContent { newtype TContentSet = TSingletonContent(Content c) or + TKnownOrUnknownArrayElementContent(TKnownArrayElementContent c) or TAnyArrayElementContent() class ContentSet extends TContentSet { @@ -426,6 +427,9 @@ class ContentSet extends TContentSet { this = TSingletonContent(result) or // for reverse stores + this = TKnownOrUnknownArrayElementContent(result) + or + // for reverse stores this = TAnyArrayElementContent() and result = TUnknownArrayElementContent() } @@ -433,6 +437,13 @@ class ContentSet extends TContentSet { Content getAReadContent() { this = TSingletonContent(result) or + exists(TKnownArrayElementContent c | + this = TKnownOrUnknownArrayElementContent(c) | + result = c + or + result = TUnknownArrayElementContent() + ) + or this = TAnyArrayElementContent() and (result = TUnknownArrayElementContent() or result = TKnownArrayElementContent(_)) } @@ -447,12 +458,10 @@ a[0] = tainted # storeStep(not_tainted, TSingletonContent(TKnownArrayElementContent(1)), [post update] a) a[1] = not_tainted -# readStep(a, TSingletonContent(TKnownArrayElementContent(0)), a[0]) -# readStep(a, TSingletonContent(TUnknownArrayElementContent()), a[0]) +# readStep(a, TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(0)), a[0]) sink(a[0]) # bad -# readStep(a, TSingletonContent(TKnownArrayElementContent(1)), a[1]) -# readStep(a, TSingletonContent(TUnknownArrayElementContent()), a[1]) +# readStep(a, TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(1)), a[1]) sink(a[1]) # good # readStep(a, TAnyArrayElementContent(), a[unknown]) @@ -461,26 +470,24 @@ sink(a[unknown]) # bad; unknown may be 0 # storeStep(tainted, TSingletonContent(TUnknownArrayElementContent()), [post update] b) b[unknown] = tainted -# readStep(b, TSingletonContent(TKnownArrayElementContent(0)), b[0]) -# readStep(b, TSingletonContent(TUnknownArrayElementContent()), b[0]) +# readStep(b, TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(0)), b[0]) sink(b[0]) # bad; unknown may be 0 -# storeStep(tainted, TSingletonContent(TKnownArrayElementContent(0)), [post update] c[unknown]) -# storeStep(not_tainted, TSingletonContent(TKnownArrayElementContent(1)), [post update] c[unknown]) -# readStep(c, TAnyArrayElementContent(), c[unknown]) -# storeStep([post update] c[unknown], TAnyArrayElementContent(), [post update] c) # auto-generated reverse store (see Example 2) -c[unknown][0] = tainted -c[unknown][1] = not_tainted +# storeStep(tainted, TSingletonContent(TUnknownArrayElementContent()), [post update] c[0]) +# storeStep(not_tainted, TSingletonContent(TUnknownArrayElementContent()), [post update] c[1]) +# readStep(c, TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(0)), c[0]) +# readStep(c, TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(1)), c[1]) +# storeStep([post update] c[0], TSingletonContent(TKnownArrayElementContent(0)), [post update] c) # auto-generated reverse store (see Example 2) +# storeStep([post update] c[1], TSingletonContent(TKnownArrayElementContent(1)), [post update] c) # auto-generated reverse store (see Example 2) +c[0][unknown] = tainted +c[1][unknown] = not_tainted - -# readStep(c[0], TSingletonContent(TKnownArrayElementContent(0)), c[0][0]) -# readStep(c[0], TSingletonContent(TUnknownArrayElementContent()), c[0][0]) -# readStep(c[0], TSingletonContent(TKnownArrayElementContent(1)), c[0][1]) -# readStep(c[0], TSingletonContent(TUnknownArrayElementContent()), c[0][1]) -# readStep(c, TSingletonContent(TKnownArrayElementContent(0)), c[0]) -# readStep(c, TSingletonContent(TUnknownArrayElementContent()), c[0]) +# readStep(c[0], TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(0)), c[0][0]) +# readStep(c[1], TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(0)), c[1][0]) +# readStep(c, TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(0)), c[0]) +# readStep(c, TKnownOrUnknownArrayElementContent(TKnownArrayElementContent(1)), c[1]) sink(c[0][0]) # bad; unknown may be 0 -sink(c[0][1]) # good +sink(c[1][0]) # good ``` ### Field flow barriers