Ruby: Add ActiveSupport extensions

This commit is contained in:
Harry Maclean 2022-10-06 13:57:53 +13:00
Родитель cb37a0e835
Коммит 71d703f2a5
3 изменённых файлов: 145 добавлений и 0 удалений

Просмотреть файл

@ -83,6 +83,74 @@ module ActiveSupport {
}
}
/**
* Extensions to the `Hash` class.
*/
module Hash {
private class WithIndifferentAccessSummary extends SimpleSummarizedCallable {
WithIndifferentAccessSummary() { this = "with_indifferent_access" }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "Argument[self].Element[any]" and
output = "ReturnValue.Element[any]" and
preservesValue = true
}
}
private class TransformSummary extends SimpleSummarizedCallable {
TransformSummary() {
this =
[
"stringify_keys", "to_options", "symbolize_keys", "deep_stringify_keys",
"deep_symbolize_keys", "with_indifferent_access"
]
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "Argument[self].Element[any]" and
output = "ReturnValue.Element[?]" and
preservesValue = true
}
}
private string getExtractComponent(MethodCall mc, int i) {
mc.getMethodName() = ["extract!"] and
result = DataFlow::Content::getKnownElementIndex(mc.getArgument(i)).serialize()
}
private class ExtractSummary extends SummarizedCallable {
MethodCall mc;
ExtractSummary() {
mc.getMethodName() = "extract!" and
this =
"extract!(" +
concat(int i, string s | s = getExtractComponent(mc, i) | s, "," order by i) + ")"
}
final override MethodCall getACall() { result = mc }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
(
exists(string s | s = getExtractComponent(mc, _) |
input = "Argument[self].Element[" + s + "!]" and
output = "ReturnValue.Element[" + s + "!]"
)
or
input =
"Argument[self]" +
concat(int i, string s |
s = getExtractComponent(mc, i)
|
".WithoutElement[" + s + "!]" order by i
) + ".WithElement[any]" and
output = "Argument[self]"
) and
preservesValue = true
}
}
}
/**
* Extensions to the `Enumerable` module.
*/

Просмотреть файл

@ -4,6 +4,7 @@
import codeql.ruby.AST
import TestUtilities.InlineFlowTest
import codeql.ruby.Frameworks
import PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf

Просмотреть файл

@ -0,0 +1,76 @@
def m_deep_merge
h1 = { a: source "a" }
h2 = { b: source "b" }
x = h1.deep_merge(h2)
sink x[:a] # $ hasValueFlow=a
sink x[:b] # $ hasValueFlow=b
end
def m_deep_merge!
h1 = { a: source "a" }
h2 = { b: source "b" }
x = h1.deep_merge!(h2)
sink x[:a] # $ hasValueFlow=a
sink x[:b] # $ hasValueFlow=b
sink h1[:a] # $ hasValueFlow=a
sink h1[:b] # $ hasValueFlow=b
sink h2[:a]
sink h2[:b] # $ hasValueFlow=b
end
def m_stringify_keys
h = { a: source "a" }
x = h.stringify_keys
sink x[:a] # $hasValueFlow=a
end
def m_to_options
h = { a: taint "a" }
x = h.to_options
sink x[:a] # $hasTaintFlow=a
end
def m_symbolize_keys
h = { a: taint "a" }
x = h.symbolize_keys
sink x[:a] # $hasTaintFlow=a
end
def m_deep_stringify_keys
h = { a: taint "a" }
x = h.deep_stringify_keys
sink x[:a] # $hasTaintFlow=a
end
def m_deep_symbolize_keys
h = { a: taint "a" }
x = h.deep_symbolize_keys
sink x[:a] # $hasTaintFlow=a
end
def m_with_indifferent_access
h = { a: taint "a" }
x = h.with_indifferent_access
sink x[:a] # $hasTaintFlow=a
end
def m_extract!(x)
h = { a: taint "a", b: taint "b", c: "c", d: taint "d" }
x = h.extract!(:a, x, :b)
sink h[:a]
sink h[:b]
sink h[:c]
sink h[:d] # $ hasValueFlow=d
sink x[:a] # $ hasValueFlow=a
sink x[:b] # $ hasValueFlow=b
sink x[:c]
sink x[:d]
end
m_extract!(:c)