Ruby: address some more feedback on array flow summaries

This commit is contained in:
Nick Rolfe
2022-02-04 16:33:27 +00:00
parent ed00f2b0d2
commit 7a9ddc28bf
3 changed files with 6563 additions and 6440 deletions

View File

@@ -843,7 +843,7 @@ module Array {
"ArrayElement of Receiver", "ArrayElement of ArrayElement of Receiver",
"ArrayElement of ArrayElement of ArrayElement of Receiver"
] and
output = "ArrayElement[?] of Receiver"
output = ["ArrayElement[?] of Receiver", "ArrayElement[?] of ReturnValue"]
) and
preservesValue = true
}
@@ -1142,6 +1142,25 @@ module Array {
}
}
private class RejectBangSummary extends SimpleSummarizedCallable {
RejectBangSummary() { this = "reject!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"ArrayElement[?] of ReturnValue", "ArrayElement[?] of Receiver",
"Parameter[0] of BlockArgument"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::ArrayElementContent
}
}
private class ReplaceSummary extends SimpleSummarizedCallable {
ReplaceSummary() { this = "replace" }
@@ -1507,14 +1526,6 @@ module Array {
)
)
}
predicate debugDeleteMe(MethodCall c, string input, string output, int s, int e, int ln) {
c = mc and
s = start and
e = end and
propagatesFlowExt(input, output, _) and
ln = mc.getLocation().getStartLine()
}
}
/**
@@ -1548,6 +1559,100 @@ module Array {
}
}
private class SortBangSummary extends SimpleSummarizedCallable {
SortBangSummary() { this = "sort!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"Parameter[0] of BlockArgument", "Parameter[1] of BlockArgument",
"ArrayElement[?] of Receiver", "ArrayElement[?] of ReturnValue"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::KnownArrayElementContent
}
}
private class SortByBangSummary extends SimpleSummarizedCallable {
SortByBangSummary() { this = "sort_by!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"Parameter[0] of BlockArgument", "ArrayElement[?] of Receiver",
"ArrayElement[?] of ReturnValue"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::KnownArrayElementContent
}
}
private class TransposeSummary extends SimpleSummarizedCallable {
TransposeSummary() { this = "transpose" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
preservesValue = true and
(
input = "ArrayElement[?] of ArrayElement[?] of Receiver" and
output = "ArrayElement[?] of ArrayElement[?] of ReturnValue"
or
exists(ArrayIndex i, ArrayIndex j |
input = "ArrayElement[" + i + "] of ArrayElement[" + j + "] of Receiver" and
output = "ArrayElement[" + j + "] of ArrayElement[" + i + "] of ReturnValue"
)
)
}
}
private class UniqBangSummary extends SimpleSummarizedCallable {
UniqBangSummary() { this = "uniq!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"ArrayElement[?] of Receiver", "ArrayElement[?] of ReturnValue",
"Parameter[0] of BlockArgument"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::KnownArrayElementContent
}
}
private class UnionSummary extends SummarizedCallable {
MethodCall mc;
UnionSummary() { this = "union" and mc.getMethodName() = this }
override MethodCall getACall() { result = mc }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
(
input = "ArrayElement of Receiver"
or
exists(int i | i in [0 .. mc.getNumberOfArguments() - 1] |
input = "ArrayElement of Argument[" + i + "]"
)
) and
output = "ArrayElement[?] of ReturnValue" and
preservesValue = true
}
}
abstract private class ValuesAtSummary extends SummarizedCallable {
MethodCall mc;
@@ -1656,7 +1761,7 @@ module Enumerable {
output = "Parameter[0] of BlockArgument" and
preservesValue = true
or
input = "ArrayElement of ReturnValue of BlockArgument" and
input = ["ArrayElement of ReturnValue of BlockArgument", "ReturnValue of BlockArgument"] and
output = "ArrayElement[?] of ReturnValue" and
preservesValue = true
}
@@ -1997,6 +2102,8 @@ module Enumerable {
or
exists(ArrayIndex i | i > 0 | input = "ArrayElement[" + i + "] of Receiver") and
output = "Parameter[1] of BlockArgument"
or
input = "ReturnValue of BlockArgument" and output = "ReturnValue"
) and
preservesValue = true
}
@@ -2014,6 +2121,8 @@ module Enumerable {
// Each element in the receiver is passed to the second block parameter.
exists(ArrayIndex i | input = "ArrayElement[" + i + "] of Receiver") and
output = "Parameter[1] of BlockArgument"
or
input = "ReturnValue of BlockArgument" and output = "ReturnValue"
) and
preservesValue = true
}
@@ -2203,25 +2312,6 @@ module Enumerable {
}
}
private class RejectBangSummary extends SimpleSummarizedCallable {
RejectBangSummary() { this = "reject!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"ArrayElement[?] of ReturnValue", "ArrayElement[?] of Receiver",
"Parameter[0] of BlockArgument"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::ArrayElementContent
}
}
private class SelectSummary extends SimpleSummarizedCallable {
// `find_all` and `filter` are aliases of `select`.
SelectSummary() { this = ["select", "find_all", "filter"] }
@@ -2267,25 +2357,6 @@ module Enumerable {
}
}
private class SortBangSummary extends SimpleSummarizedCallable {
SortBangSummary() { this = "sort!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"Parameter[0] of BlockArgument", "Parameter[1] of BlockArgument",
"ArrayElement[?] of Receiver", "ArrayElement[?] of ReturnValue"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::KnownArrayElementContent
}
}
private class SortBySummary extends SimpleSummarizedCallable {
SortBySummary() { this = "sort_by" }
@@ -2296,25 +2367,6 @@ module Enumerable {
}
}
private class SortByBangSummary extends SimpleSummarizedCallable {
SortByBangSummary() { this = "sort_by!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"Parameter[0] of BlockArgument", "ArrayElement[?] of Receiver",
"ArrayElement[?] of ReturnValue"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::KnownArrayElementContent
}
}
private class SumSummary extends SimpleSummarizedCallable {
SumSummary() { this = "sum" }
@@ -2377,7 +2429,7 @@ module Enumerable {
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output = ["Parameter[0] of BlockArgument"] and
output = "Parameter[0] of BlockArgument" and
preservesValue = true
or
// We can't know the size of the return value, but we know that indices
@@ -2401,43 +2453,6 @@ module Enumerable {
}
}
private class TransposeSummary extends SimpleSummarizedCallable {
TransposeSummary() { this = "transpose" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
preservesValue = true and
(
input = "ArrayElement[?] of ArrayElement[?] of Receiver" and
output = "ArrayElement[?] of ArrayElement[?] of ReturnValue"
or
exists(ArrayIndex i, ArrayIndex j |
input = "ArrayElement[" + i + "] of ArrayElement[" + j + "] of Receiver" and
output = "ArrayElement[" + j + "] of ArrayElement[" + i + "] of ReturnValue"
)
)
}
}
private class UnionSummary extends SummarizedCallable {
MethodCall mc;
UnionSummary() { this = "union" and mc.getMethodName() = this }
override MethodCall getACall() { result = mc }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
(
input = "ArrayElement of Receiver"
or
exists(int i | i in [0 .. mc.getNumberOfArguments() - 1] |
input = "ArrayElement of Argument[" + i + "]"
)
) and
output = "ArrayElement[?] of ReturnValue" and
preservesValue = true
}
}
private class UniqSummary extends SimpleSummarizedCallable {
UniqSummary() { this = "uniq" }
@@ -2448,25 +2463,6 @@ module Enumerable {
}
}
private class UniqBangSummary extends SimpleSummarizedCallable {
UniqBangSummary() { this = "uniq!" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "ArrayElement of Receiver" and
output =
[
"ArrayElement[?] of Receiver", "ArrayElement[?] of ReturnValue",
"Parameter[0] of BlockArgument"
] and
preservesValue = true
}
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
pos.isSelf() and
content instanceof DataFlow::Content::KnownArrayElementContent
}
}
abstract private class ZipSummary extends SummarizedCallable {
MethodCall mc;
@@ -2504,7 +2500,7 @@ module Enumerable {
output = "ArrayElement[0] of ArrayElement[" + i + "] of ReturnValue"
)
or
// receiver[?] -> return_value[0][?]
// receiver[?] -> return_value[?][0]
input = "ArrayElement[?] of Receiver" and
output = "ArrayElement[0] of ArrayElement[?] of ReturnValue"
or

View File

@@ -253,6 +253,11 @@ def m28
[x, source(28.2)]
end
sink(b[0]) # $ hasValueFlow=28.1 $ hasValueFlow=28.2
b = a.collect_concat do |x|
sink(x) # $ hasValueFlow=28.1
source(28.2)
end
sink b[0] # $ hasValueFlow=28.2
end
def m29
@@ -557,6 +562,11 @@ def m62
[x, source(62.2)]
end
sink(b[0]) # $ hasValueFlow=62.1 $ hasValueFlow=62.2
b = a.flat_map do |x|
sink(x) # $ hasValueFlow=62.1
source(62.2)
end
sink b[0] # $ hasValueFlow=62.2
end
def m63
@@ -568,9 +578,11 @@ end
def m64
a = [0, 1, [2, source(64)]]
sink(a[2][1]) # $ hasValueFlow=64
a.flatten!
b = a.flatten!
sink(a[0]) # $ hasValueFlow=64
sink(a[2][1]) # $ SPURIOUS: hasValueFlow=64
sink(b[0]) # $ hasValueFlow=64
sink(b[2][1]) # $ SPURIOUS: hasValueFlow=64
end
def m65
@@ -616,13 +628,15 @@ def m69
b = a.inject do |x, y|
sink x # $ hasValueFlow=69.1
sink y # $ hasValueFlow=69.2
x + y
source 69.3
end
sink b # $ hasValueFlow=69.3
c = a.inject(0) do |x, y|
sink x
sink y # $ hasValueFlow=69.1 $ hasValueFlow=69.2
x + y
source 69.3
end
sink c # $ hasValueFlow=69.3
end
def m70(i)