diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/go.mod b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/go.mod new file mode 100644 index 00000000000..709117ebc26 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/go.mod @@ -0,0 +1,5 @@ +module semmle.go.Packages + +go 1.13 + +require github.com/nonexistent-test-pkg v0.0.0-20200203000000-0000000000000 diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/sinks.expected b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/sinks.expected new file mode 100644 index 00000000000..de1751aea90 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/sinks.expected @@ -0,0 +1,3 @@ +invalidModelRow +#select +| test.go:40:10:40:12 | arg | qltest | diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/sinks.ql b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/sinks.ql new file mode 100644 index 00000000000..ef8af3a321c --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/sinks.ql @@ -0,0 +1,19 @@ +import go +import semmle.go.dataflow.DataFlow +import semmle.go.dataflow.ExternalFlow +import CsvValidation + +class SinkModelTest extends SinkModelCsv { + override predicate row(string row) { + row = + [ + //`namespace; type; subtypes; name; -; ext; input; kind` + "github.com/nonexistent/test;B;false;Sink1;;;Argument[0];qltest", + "github.com/nonexistent/test;B;false;SinkMethod;;;ReturnValue;qltest" + ] + } +} + +from DataFlow::Node node, string kind +where sinkNode(node, kind) +select node, kind diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/srcs.expected b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/srcs.expected new file mode 100644 index 00000000000..1c9cfbdb953 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/srcs.expected @@ -0,0 +1,11 @@ +invalidModelRow +#select +| test.go:11:6:11:8 | definition of arg | qltest-arg | +| test.go:28:6:28:6 | definition of a | qltest-arg | +| test.go:31:8:31:15 | call to Src1 | qltest | +| test.go:32:8:32:15 | call to Src2 | qltest | +| test.go:32:8:32:15 | call to Src2 | qltest-w-subtypes | +| test.go:33:8:33:16 | call to Src2 | qltest-w-subtypes | +| test.go:34:2:34:21 | ... = ...[0] | qltest | +| test.go:34:2:34:21 | ... = ...[1] | qltest-w-subtypes | +| test.go:35:2:35:22 | ... = ...[1] | qltest-w-subtypes | diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/srcs.ql b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/srcs.ql new file mode 100644 index 00000000000..72e728271f9 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/srcs.ql @@ -0,0 +1,23 @@ +import go +import semmle.go.dataflow.DataFlow +import semmle.go.dataflow.ExternalFlow +import CsvValidation + +class SourceModelTest extends SourceModelCsv { + override predicate row(string row) { + row = + [ + //`namespace; type; subtypes; name; -; ext; output; kind` + "github.com/nonexistent/test;A;false;Src1;;;ReturnValue;qltest", + "github.com/nonexistent/test;A;false;Src2;;;ReturnValue;qltest", + "github.com/nonexistent/test;A;true;Src2;;;ReturnValue;qltest-w-subtypes", + "github.com/nonexistent/test;A;false;SrcArg;;;Argument;qltest-arg", + "github.com/nonexistent/test;A;false;Src3;;;ReturnValue[0];qltest", + "github.com/nonexistent/test;A;true;Src3;;;ReturnValue[1];qltest-w-subtypes" + ] + } +} + +from DataFlow::Node node, string kind +where sourceNode(node, kind) +select node, kind diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/steps.expected b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/steps.expected new file mode 100644 index 00000000000..375470ab2a2 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/steps.expected @@ -0,0 +1,9 @@ +invalidModelRow +#select +| test.go:16:23:16:25 | arg | test.go:16:10:16:26 | call to StepArgRes | +| test.go:17:27:17:29 | arg | test.go:17:2:17:30 | ... = ...[1] | +| test.go:18:15:18:17 | arg | test.go:12:6:12:9 | definition of arg1 | +| test.go:19:16:19:18 | arg | test.go:13:6:13:6 | definition of t | +| test.go:20:10:20:10 | t | test.go:20:10:20:24 | call to StepQualRes | +| test.go:21:2:21:2 | t | test.go:11:6:11:8 | definition of arg | +| test.go:22:32:22:34 | arg | test.go:22:10:22:35 | call to StepArgResNoQual | diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/steps.ql b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/steps.ql new file mode 100644 index 00000000000..11662dbab04 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/steps.ql @@ -0,0 +1,27 @@ +import go +import semmle.go.dataflow.DataFlow +import semmle.go.dataflow.ExternalFlow +import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl +import CsvValidation + +class SummaryModelTest extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //`namespace; type; subtypes; name; -; ext; input; output; kind` + "github.com/nonexistent/test;T;false;StepArgRes;;;Argument[0];ReturnValue;taint", + "github.com/nonexistent/test;T;false;StepArgRes1;;;Argument[0];ReturnValue[1];taint", + "github.com/nonexistent/test;T;false;StepArgArg;;;Argument[0];Argument[1];taint", + "github.com/nonexistent/test;T;false;StepArgQual;;;Argument[0];Argument[-1];taint", + "github.com/nonexistent/test;T;false;StepQualRes;;;Argument[-1];ReturnValue;taint", + "github.com/nonexistent/test;T;false;StepQualArg;;;Argument[-1];Argument[0];taint", + "github.com/nonexistent/test;;false;StepArgResNoQual;;;Argument[0];ReturnValue;taint", + "github.com/nonexistent/test;;false;StepArgResContent;;;Argument[0];Element of ReturnValue;taint", + "github.com/nonexistent/test;;false;StepArgContentRes;;;ArrayElement of Argument[0];ReturnValue;taint" + ] + } +} + +from DataFlow::Node node1, DataFlow::Node node2 +where FlowSummaryImpl::Private::Steps::summaryThroughStep(node1, node2, false) +select node1, node2 diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/test.go b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/test.go new file mode 100644 index 00000000000..10a7141dcd0 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/test.go @@ -0,0 +1,44 @@ +package main + +import ( + "github.com/nonexistent/test" + "io" +) + +func use(args ...interface{}) {} + +func main() { + var arg interface{} + var arg1 interface{} + var t *test.T + var taint interface{} + + taint = t.StepArgRes(arg) + _, taint = t.StepArgRes1(arg) + t.StepArgArg(arg, arg1) + t.StepArgQual(arg) + taint = t.StepQualRes() + t.StepQualArg(arg) + taint = test.StepArgResNoQual(arg) + taint = test.StepArgResContent(arg) + taint = test.StepArgContentRes(arg) + + var src interface{} + var src1 interface{} + var a test.A + var a1 test.A1 + + src = a.Src1() + src = a.Src2() + src = a1.Src2() + src, src1 = a.Src3() + src, src1 = a1.Src3() + a.SrcArg(arg) + + var b test.B + + b.Sink1(arg) + b.SinkMethod().(io.Writer).Write(arg.([]byte)) + + use(arg, arg1, t, taint, src, src1) +} diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/vendor/github.com/nonexistent/test/stub.go b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/vendor/github.com/nonexistent/test/stub.go new file mode 100644 index 00000000000..c083880da56 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/vendor/github.com/nonexistent/test/stub.go @@ -0,0 +1,43 @@ +package test + +type T struct{} + +func (t *T) StepArgRes(arg interface{}) interface{} { return nil } + +func (t *T) StepArgRes1(arg interface{}) (interface{}, interface{}) { return nil, nil } + +func (t *T) StepArgArg(a1 interface{}, a2 interface{}) {} + +func (t *T) StepArgQual(arg interface{}) {} + +func (t *T) StepQualRes() interface{} { return nil } + +func (t *T) StepQualArg(arg interface{}) {} + +func StepArgResNoQual(arg interface{}) interface{} { return nil } + +func StepArgResContent(arg interface{}) []interface{} { return nil } + +func StepArgContentRes(arg interface{}) interface{} { return nil } + +type A interface { + Src1() interface{} + Src2() interface{} + Src3() (interface{}, interface{}) + SrcArg(arg interface{}) +} + +type A1 struct{} + +func (a *A1) Src1() interface{} { return nil } + +func (a *A1) Src2() interface{} { return nil } + +func (a *A1) Src3() (interface{}, interface{}) { return nil, nil } + +func (a *A1) SrcArg(arg interface{}) {} + +type B interface { + Sink1(arg interface{}) + SinkMethod() interface{} +} diff --git a/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/vendor/modules.txt b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/vendor/modules.txt new file mode 100644 index 00000000000..e46a0af8429 --- /dev/null +++ b/ql/test/library-tests/semmle/go/dataflow/ExternalFlow/vendor/modules.txt @@ -0,0 +1,2 @@ +# github.com/nonexistent-test-pkg v0.0.0-20200203000000-0000000000000 +github.com/nonexistent-test-package