Files
codeql/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql
2022-03-16 12:51:14 +01:00

135 lines
4.4 KiB
Plaintext

/**
* @kind path-problem
*/
import ruby
import codeql.ruby.dataflow.FlowSummary
import DataFlow::PathGraph
import codeql.ruby.TaintTracking
import codeql.ruby.dataflow.internal.FlowSummaryImpl
import codeql.ruby.dataflow.internal.AccessPathSyntax
import codeql.ruby.frameworks.data.ModelsAsData
query predicate invalidSpecComponent(SummarizedCallable sc, string s, string c) {
(sc.propagatesFlowExt(s, _, _) or sc.propagatesFlowExt(_, s, _)) and
Private::External::invalidSpecComponent(s, c)
}
query predicate warning = ModelOutput::getAWarning/0;
query predicate invalidOutputSpecComponent(SummarizedCallable sc, AccessPath s, AccessPathToken c) {
sc.propagatesFlowExt(_, s, _) and
c = s.getToken(_) and
c = "ArrayElement" // not allowed in output specs; use `ArrayElement[?] instead
}
private class SummarizedCallableIdentity extends SummarizedCallable {
SummarizedCallableIdentity() { this = "identity" }
override MethodCall getACall() { result.getMethodName() = this }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "Argument[0]" and
output = "ReturnValue" and
preservesValue = true
}
}
private class SummarizedCallableApplyBlock extends SummarizedCallable {
SummarizedCallableApplyBlock() { this = "apply_block" }
override MethodCall getACall() { result.getMethodName() = this }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "Argument[0]" and
output = "BlockArgument.Parameter[0]" and
preservesValue = true
or
input = "BlockArgument.ReturnValue" and
output = "ReturnValue" and
preservesValue = true
}
}
private class SummarizedCallableApplyLambda extends SummarizedCallable {
SummarizedCallableApplyLambda() { this = "apply_lambda" }
override MethodCall getACall() { result.getMethodName() = this }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "Argument[1]" and
output = "Argument[0].Parameter[0]" and
preservesValue = true
or
input = "Argument[0].ReturnValue" and
output = "ReturnValue" and
preservesValue = true
}
}
private class StepsFromModel extends ModelInput::SummaryModelCsv {
override predicate row(string row) {
row =
[
";;Member[Foo].Method[firstArg];Argument[0];ReturnValue;taint",
";;Member[Foo].Method[secondArg];Argument[1];ReturnValue;taint",
";;Member[Foo].Method[onlyWithoutBlock].WithoutBlock;Argument[0];ReturnValue;taint",
";;Member[Foo].Method[onlyWithBlock].WithBlock;Argument[0];ReturnValue;taint",
";;Member[Foo].Method[blockArg].BlockArgument.Parameter[0].Method[preserveTaint];Argument[0];ReturnValue;taint",
";any;Method[matchedByName];Argument[0];ReturnValue;taint",
";any;Method[matchedByNameRcv];Receiver;ReturnValue;taint",
]
}
}
private class TypeFromModel extends ModelInput::TypeModelCsv {
override predicate row(string row) {
row =
[
"test;FooOrBar;;;Member[Foo].Instance", //
"test;FooOrBar;;;Member[Bar].Instance", //
"test;FooOrBar;test;FooOrBar;Method[next].ReturnValue",
]
}
}
private class InvalidTypeModel extends ModelInput::TypeModelCsv {
override predicate row(string row) {
row =
[
"test;TooManyColumns;;;Member[Foo].Instance;too;many;columns", //
"test;TooFewColumns", //
"test;X;test;Y;Method[foo].Arg[0]", //
"test;X;test;Y;Method[foo].Argument[0-1]", //
"test;X;test;Y;Method[foo].Argument[*]", //
"test;X;test;Y;Method[foo].Argument", //
"test;X;test;Y;Method[foo].Member", //
]
}
}
private class SinkFromModel extends ModelInput::SinkModelCsv {
override predicate row(string row) { row = "test;FooOrBar;Method[method].Argument[0];test-sink" }
}
class Conf extends TaintTracking::Configuration {
Conf() { this = "FlowSummaries" }
override predicate isSource(DataFlow::Node src) {
src.asExpr().getExpr().(StringLiteral).getConstantValue().isString("taint")
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc |
mc.getMethodName() = "sink" and
mc.getAnArgument() = sink.asExpr().getExpr()
)
or
sink = ModelOutput::getASinkNode("test-sink").getARhs()
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf
where conf.hasFlowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()