diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.expected b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.expected new file mode 100644 index 00000000000..81332464f79 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.expected @@ -0,0 +1,2 @@ +failures +invalidModelRow diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.ql b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.ql new file mode 100644 index 00000000000..d7e78660a05 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/Flows.ql @@ -0,0 +1,72 @@ +import go +import semmle.go.dataflow.ExternalFlow +import CsvValidation +import TestUtilities.InlineExpectationsTest + +class SummaryModelTest extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //`namespace; type; subtypes; name; signature; ext; input; output; kind` + "github.com/nonexistent/test;;false;FunctionWithParameter;;;Argument[0];ReturnValue;value", + "github.com/nonexistent/test;;false;FunctionWithSliceParameter;;;ArrayElement of Argument[0];ReturnValue;value", + "github.com/nonexistent/test;;false;FunctionWithVarArgsParameter;;;ArrayElement of Argument[0];ReturnValue;value", + "github.com/nonexistent/test;;false;FunctionWithSliceOfStructsParameter;;;Field[github.com/nonexistent/test.A.Field] of ArrayElement of Argument[0];ReturnValue;value", + "github.com/nonexistent/test;;false;FunctionWithVarArgsOfStructsParameter;;;Field[github.com/nonexistent/test.A.Field] of ArrayElement of Argument[0];ReturnValue;value", + ] + } +} + +class DataConfiguration extends DataFlow::Configuration { + DataConfiguration() { this = "data-configuration" } + + override predicate isSource(DataFlow::Node source) { + source = any(DataFlow::CallNode c | c.getCalleeName() = "source").getResult(0) + } + + override predicate isSink(DataFlow::Node sink) { + sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0) + } +} + +class DataFlowTest extends InlineExpectationsTest { + DataFlowTest() { this = "DataFlowTest" } + + override string getARelevantTag() { result = "dataflow" } + + override predicate hasActualResult(string file, int line, string element, string tag, string value) { + tag = "dataflow" and + exists(DataFlow::Node sink | any(DataConfiguration c).hasFlow(_, sink) | + element = sink.toString() and + value = "" and + sink.hasLocationInfo(file, line, _, _, _) + ) + } +} + +class TaintConfiguration extends TaintTracking::Configuration { + TaintConfiguration() { this = "taint-configuration" } + + override predicate isSource(DataFlow::Node source) { + source = any(DataFlow::CallNode c | c.getCalleeName() = "source").getResult(0) + } + + override predicate isSink(DataFlow::Node sink) { + sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0) + } +} + +class TaintFlowTest extends InlineExpectationsTest { + TaintFlowTest() { this = "TaintFlowTest" } + + override string getARelevantTag() { result = "taintflow" } + + override predicate hasActualResult(string file, int line, string element, string tag, string value) { + tag = "taintflow" and + exists(DataFlow::Node sink | any(TaintConfiguration c).hasFlow(_, sink) | + element = sink.toString() and + value = "" and + sink.hasLocationInfo(file, line, _, _, _) + ) + } +} diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/go.mod b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/go.mod new file mode 100644 index 00000000000..ed18764ed28 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/go.mod @@ -0,0 +1,5 @@ +module semmle.go.Packages + +go 1.17 + +require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000 diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/main.go b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/main.go new file mode 100644 index 00000000000..40c2d31149b --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "github.com/nonexistent/test" +) + +func source() string { + return "untrusted data" +} + +func sink(string) { +} + +func main() { + s := source() + sink(test.FunctionWithParameter(s)) // $ taintflow dataflow + + stringSlice := []string{source()} + sink(stringSlice[0]) // $ taintflow dataflow + + s0 := "" + s1 := source() + sSlice := []string{s0, s1} + sink(test.FunctionWithParameter(sSlice[1])) // $ taintflow dataflow + sink(test.FunctionWithSliceParameter(sSlice)) // $ taintflow dataflow + sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ taintflow dataflow + sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ MISSING: taintflow dataflow + + sliceOfStructs := []test.A{{Field: source()}} + sink(sliceOfStructs[0].Field) // $ taintflow dataflow + + a0 := test.A{Field: ""} + a1 := test.A{Field: source()} + aSlice := []test.A{a0, a1} + sink(test.FunctionWithSliceOfStructsParameter(aSlice)) // $ taintflow dataflow + sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ taintflow dataflow + sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ MISSING: taintflow dataflow +} diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/semmle.go.Packages b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/semmle.go.Packages new file mode 100755 index 00000000000..e3880ac8d5d Binary files /dev/null and b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/semmle.go.Packages differ diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/vendor/github.com/nonexistent/test/stub.go b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/vendor/github.com/nonexistent/test/stub.go new file mode 100644 index 00000000000..66f3da7d659 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/vendor/github.com/nonexistent/test/stub.go @@ -0,0 +1,25 @@ +package test + +type A struct { + Field string +} + +func FunctionWithParameter(s string) string { + return "" +} + +func FunctionWithSliceParameter(s []string) string { + return "" +} + +func FunctionWithVarArgsParameter(s ...string) string { + return "" +} + +func FunctionWithSliceOfStructsParameter(s []A) string { + return "" +} + +func FunctionWithVarArgsOfStructsParameter(s ...A) string { + return "" +} diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/vendor/modules.txt b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/vendor/modules.txt new file mode 100644 index 00000000000..b62dbf8819b --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlowVarArgs/vendor/modules.txt @@ -0,0 +1,3 @@ +# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000 +## explicit +github.com/nonexistent/test