Ruby: Fix spurious flow through reverse stores

This commit is contained in:
Tom Hvitved
2022-09-26 19:35:36 +02:00
parent fea1e47daa
commit 2351c0288a
8 changed files with 184 additions and 111 deletions

View File

@@ -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. */

View File

@@ -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

View File

@@ -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()
)
}
}

View File

@@ -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))
}
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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 : |

View File

@@ -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