From 64baf65af09da0ee6ec17fd2b0c16319990db6af Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 12 Sep 2024 17:04:21 +0100 Subject: [PATCH] Add tests for MaD inheritance --- .../dataflow/ExternalFlowInheritance/go.mod | 5 + .../mad_interface_subtypes_false.expected | 10 ++ .../mad_interface_subtypes_false.ext.yml | 16 +++ .../mad_interface_subtypes_false.ql | 18 +++ .../mad_interface_subtypes_true.expected | 40 +++++++ .../mad_interface_subtypes_true.ext.yml | 16 +++ .../mad_interface_subtypes_true.ql | 18 +++ .../mad_struct_subtypes_false.expected | 10 ++ .../mad_struct_subtypes_false.ext.yml | 16 +++ .../mad_struct_subtypes_false.ql | 18 +++ .../mad_struct_subtypes_true.expected | 10 ++ .../mad_struct_subtypes_true.ext.yml | 16 +++ .../mad_struct_subtypes_true.ql | 18 +++ .../ql_models_interface.expected | 10 ++ .../ql_models_interface.ql | 46 +++++++ .../ql_models_struct.expected | 16 +++ .../ql_models_struct.ql | 46 +++++++ .../dataflow/ExternalFlowInheritance/test.go | 77 ++++++++++++ .../github.com/nonexistent/test/stub.go | 112 ++++++++++++++++++ .../vendor/modules.txt | 3 + 20 files changed, 521 insertions(+) create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/go.mod create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ext.yml create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/modules.txt diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/go.mod b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/go.mod new file mode 100644 index 0000000000000..57813acac5582 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/go.mod @@ -0,0 +1,5 @@ +module semmle.go.Packages + +go 1.21 + +require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000 diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.expected new file mode 100644 index 0000000000000..1a6dc55986ca9 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.expected @@ -0,0 +1,10 @@ +invalidModelRow +paths +| test.go:8:7:8:16 | call to Source | test.go:10:9:10:9 | y | +| test.go:32:7:32:16 | call to Source | test.go:34:9:34:9 | y | +sources +| test.go:8:7:8:16 | call to Source | +| test.go:32:7:32:16 | call to Source | +sinks +| test.go:10:9:10:9 | y | +| test.go:34:9:34:9 | y | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ext.yml new file mode 100644 index 0000000000000..11067b1760da2 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "I1", False, "Source", "", "", "ReturnValue", "remote", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "I1", False, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "I1", False, "Sink", "", "", "Argument[0]", "path-injection", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ql new file mode 100644 index 0000000000000..e1f1ca3bd6295 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_false.ql @@ -0,0 +1,18 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sources(source) } + + predicate isSink(DataFlow::Node sink) { sinks(sink) } +} + +module Flow = DataFlow::Global; + +query predicate paths(DataFlow::Node source, DataFlow::Node sink) { Flow::flow(source, sink) } + +query predicate sources(DataFlow::Node source) { source instanceof RemoteFlowSource } + +query predicate sinks(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.expected new file mode 100644 index 0000000000000..369f3c666035c --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.expected @@ -0,0 +1,40 @@ +invalidModelRow +paths +| test.go:8:7:8:16 | call to Source | test.go:10:9:10:9 | y | +| test.go:14:7:14:16 | call to Source | test.go:16:9:16:9 | y | +| test.go:20:7:20:16 | call to Source | test.go:22:9:22:9 | y | +| test.go:26:7:26:16 | call to Source | test.go:28:9:28:9 | y | +| test.go:32:7:32:16 | call to Source | test.go:34:9:34:9 | y | +| test.go:38:7:38:16 | call to Source | test.go:40:9:40:9 | y | +| test.go:44:7:44:16 | call to Source | test.go:46:9:46:9 | y | +| test.go:50:7:50:16 | call to Source | test.go:52:9:52:9 | y | +| test.go:56:7:56:16 | call to Source | test.go:58:9:58:9 | y | +| test.go:62:7:62:16 | call to Source | test.go:64:9:64:9 | y | +| test.go:68:7:68:16 | call to Source | test.go:70:9:70:9 | y | +| test.go:74:7:74:16 | call to Source | test.go:76:9:76:9 | y | +sources +| test.go:8:7:8:16 | call to Source | +| test.go:14:7:14:16 | call to Source | +| test.go:20:7:20:16 | call to Source | +| test.go:26:7:26:16 | call to Source | +| test.go:32:7:32:16 | call to Source | +| test.go:38:7:38:16 | call to Source | +| test.go:44:7:44:16 | call to Source | +| test.go:50:7:50:16 | call to Source | +| test.go:56:7:56:16 | call to Source | +| test.go:62:7:62:16 | call to Source | +| test.go:68:7:68:16 | call to Source | +| test.go:74:7:74:16 | call to Source | +sinks +| test.go:10:9:10:9 | y | +| test.go:16:9:16:9 | y | +| test.go:22:9:22:9 | y | +| test.go:28:9:28:9 | y | +| test.go:34:9:34:9 | y | +| test.go:40:9:40:9 | y | +| test.go:46:9:46:9 | y | +| test.go:52:9:52:9 | y | +| test.go:58:9:58:9 | y | +| test.go:64:9:64:9 | y | +| test.go:70:9:70:9 | y | +| test.go:76:9:76:9 | y | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ext.yml new file mode 100644 index 0000000000000..48c3a4daca8c0 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "I1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "I1", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "I1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ql new file mode 100644 index 0000000000000..e1f1ca3bd6295 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_interface_subtypes_true.ql @@ -0,0 +1,18 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sources(source) } + + predicate isSink(DataFlow::Node sink) { sinks(sink) } +} + +module Flow = DataFlow::Global; + +query predicate paths(DataFlow::Node source, DataFlow::Node sink) { Flow::flow(source, sink) } + +query predicate sources(DataFlow::Node source) { source instanceof RemoteFlowSource } + +query predicate sinks(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.expected new file mode 100644 index 0000000000000..2b6a7e9422837 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.expected @@ -0,0 +1,10 @@ +invalidModelRow +paths +| test.go:20:7:20:16 | call to Source | test.go:22:9:22:9 | y | +| test.go:56:7:56:16 | call to Source | test.go:58:9:58:9 | y | +sources +| test.go:20:7:20:16 | call to Source | +| test.go:56:7:56:16 | call to Source | +sinks +| test.go:22:9:22:9 | y | +| test.go:58:9:58:9 | y | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ext.yml new file mode 100644 index 0000000000000..b0322a6ecd309 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "S1", False, "Source", "", "", "ReturnValue", "remote", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "S1", False, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "S1", False, "Sink", "", "", "Argument[0]", "path-injection", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ql new file mode 100644 index 0000000000000..e1f1ca3bd6295 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_false.ql @@ -0,0 +1,18 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sources(source) } + + predicate isSink(DataFlow::Node sink) { sinks(sink) } +} + +module Flow = DataFlow::Global; + +query predicate paths(DataFlow::Node source, DataFlow::Node sink) { Flow::flow(source, sink) } + +query predicate sources(DataFlow::Node source) { source instanceof RemoteFlowSource } + +query predicate sinks(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.expected new file mode 100644 index 0000000000000..2b6a7e9422837 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.expected @@ -0,0 +1,10 @@ +invalidModelRow +paths +| test.go:20:7:20:16 | call to Source | test.go:22:9:22:9 | y | +| test.go:56:7:56:16 | call to Source | test.go:58:9:58:9 | y | +sources +| test.go:20:7:20:16 | call to Source | +| test.go:56:7:56:16 | call to Source | +sinks +| test.go:22:9:22:9 | y | +| test.go:58:9:58:9 | y | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ext.yml new file mode 100644 index 0000000000000..3adf2d35ca48f --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ext.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["github.com/nonexistent/test", "S1", True, "Source", "", "", "ReturnValue", "remote", "manual"] + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["github.com/nonexistent/test", "S1", True, "Step", "", "", "Argument[0]", "ReturnValue", "value", "manual"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/nonexistent/test", "S1", True, "Sink", "", "", "Argument[0]", "path-injection", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ql new file mode 100644 index 0000000000000..e1f1ca3bd6295 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/mad_struct_subtypes_true.ql @@ -0,0 +1,18 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sources(source) } + + predicate isSink(DataFlow::Node sink) { sinks(sink) } +} + +module Flow = DataFlow::Global; + +query predicate paths(DataFlow::Node source, DataFlow::Node sink) { Flow::flow(source, sink) } + +query predicate sources(DataFlow::Node source) { source instanceof RemoteFlowSource } + +query predicate sinks(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.expected new file mode 100644 index 0000000000000..1a6dc55986ca9 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.expected @@ -0,0 +1,10 @@ +invalidModelRow +paths +| test.go:8:7:8:16 | call to Source | test.go:10:9:10:9 | y | +| test.go:32:7:32:16 | call to Source | test.go:34:9:34:9 | y | +sources +| test.go:8:7:8:16 | call to Source | +| test.go:32:7:32:16 | call to Source | +sinks +| test.go:10:9:10:9 | y | +| test.go:34:9:34:9 | y | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.ql new file mode 100644 index 0000000000000..bf113c3330c61 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_interface.ql @@ -0,0 +1,46 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl + +class MySource extends RemoteFlowSource::Range instanceof DataFlow::Node { + MySource() { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "I1", "Source") and + this = m.getACall().getResult() + ) + } +} + +class MyStep extends DataFlow::FunctionModel, Method { + MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "I1", "Step") } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + input.isParameter(0) and output.isResult() + } +} + +class MySink extends FileSystemAccess::Range, DataFlow::CallNode { + MySink() { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "I1", "Sink") and + this = m.getACall() + ) + } + + override DataFlow::Node getAPathArgument() { result = this.getArgument(0) } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sources(source) } + + predicate isSink(DataFlow::Node sink) { sinks(sink) } +} + +module Flow = DataFlow::Global; + +query predicate paths(DataFlow::Node source, DataFlow::Node sink) { Flow::flow(source, sink) } + +query predicate sources(DataFlow::Node source) { source instanceof RemoteFlowSource } + +query predicate sinks(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.expected new file mode 100644 index 0000000000000..5f186108a583f --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.expected @@ -0,0 +1,16 @@ +invalidModelRow +paths +| test.go:8:7:8:16 | call to Source | test.go:10:9:10:9 | y | +| test.go:20:7:20:16 | call to Source | test.go:22:9:22:9 | y | +| test.go:32:7:32:16 | call to Source | test.go:34:9:34:9 | y | +| test.go:56:7:56:16 | call to Source | test.go:58:9:58:9 | y | +sources +| test.go:8:7:8:16 | call to Source | +| test.go:20:7:20:16 | call to Source | +| test.go:32:7:32:16 | call to Source | +| test.go:56:7:56:16 | call to Source | +sinks +| test.go:10:9:10:9 | y | +| test.go:22:9:22:9 | y | +| test.go:34:9:34:9 | y | +| test.go:58:9:58:9 | y | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.ql new file mode 100644 index 0000000000000..6d9371308efe0 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_models_struct.ql @@ -0,0 +1,46 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl + +class MySource extends RemoteFlowSource::Range instanceof DataFlow::Node { + MySource() { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "S1", "Source") and + this = m.getACall().getResult() + ) + } +} + +class MyStep extends DataFlow::FunctionModel, Method { + MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "S1", "Step") } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + input.isParameter(0) and output.isResult() + } +} + +class MySink extends FileSystemAccess::Range, DataFlow::CallNode { + MySink() { + exists(Method m | + m.hasQualifiedName("github.com/nonexistent/test", "S1", "Sink") and + this = m.getACall() + ) + } + + override DataFlow::Node getAPathArgument() { result = this.getArgument(0) } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { sources(source) } + + predicate isSink(DataFlow::Node sink) { sinks(sink) } +} + +module Flow = DataFlow::Global; + +query predicate paths(DataFlow::Node source, DataFlow::Node sink) { Flow::flow(source, sink) } + +query predicate sources(DataFlow::Node source) { source instanceof RemoteFlowSource } + +query predicate sinks(DataFlow::Node sink) { sink = any(FileSystemAccess fsa).getAPathArgument() } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go new file mode 100644 index 0000000000000..87e6eab8532cd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/test.go @@ -0,0 +1,77 @@ +package main + +import ( + "github.com/nonexistent/test" +) + +func TestI1(t test.I1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestI2(t test.I2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestS1(t test.S1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestS2(t test.S2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingI1(t test.StructEmbeddingI1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingI2(t test.StructEmbeddingI2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingAndOverridingI1(t test.StructEmbeddingAndOverridingI1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingAndOverridingI2(t test.StructEmbeddingAndOverridingI2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingS1(t test.StructEmbeddingS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingS2(t test.StructEmbeddingS2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingAndOverridingS1(t test.StructEmbeddingAndOverridingS1) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} + +func TestStructEmbeddingAndOverridingS2(t test.StructEmbeddingAndOverridingS2) { + x := t.Source() + y := t.Step(x) + t.Sink(y) +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go new file mode 100644 index 0000000000000..9e5ec515b0bd5 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/github.com/nonexistent/test/stub.go @@ -0,0 +1,112 @@ +package test + +// An interface +type I1 interface { + Source() interface{} + Step(interface{}) interface{} + Sink(interface{}) +} + +// An interface which is a subtype of I1 +type I2 interface { + Source() interface{} + Step(interface{}) interface{} + Sink(interface{}) + ExtraMethod() +} + +// A struct type implementing I1 +type S1 struct{} + +func (t *S1) Source() interface{} { + return nil +} + +func (t *S1) Sink(interface{}) {} + +func (t *S1) Step(val interface{}) interface{} { + return val +} + +// A struct type implementing I2 +type S2 struct{} + +func (t *S2) Source() interface{} { + return nil +} + +func (t *S2) Sink(interface{}) {} + +func (t *S2) Step(val interface{}) interface{} { + return val +} + +func (t *S2) ExtraMethod() {} + +// A struct type embedding I1 +type StructEmbeddingI1 struct{ I1 } + +// A struct type embedding I2 +type StructEmbeddingI2 struct{ I2 } + +// A struct type embedding I1 and "overriding" its methods +type StructEmbeddingAndOverridingI1 struct{ I1 } + +func (t *StructEmbeddingAndOverridingI1) Source() interface{} { + return nil +} + +func (t *StructEmbeddingAndOverridingI1) Sink(interface{}) {} + +func (t *StructEmbeddingAndOverridingI1) Step(val interface{}) interface{} { + return val +} + +// A struct type embedding I2 and "overriding" its methods +type StructEmbeddingAndOverridingI2 struct{ I2 } + +func (t *StructEmbeddingAndOverridingI2) Source() interface{} { + return nil +} + +func (t *StructEmbeddingAndOverridingI2) Sink(interface{}) {} + +func (t *StructEmbeddingAndOverridingI2) Step(val interface{}) interface{} { + return val +} + +func (t *StructEmbeddingAndOverridingI2) ExtraMethod() {} + +// A struct type embedding S1 +type StructEmbeddingS1 struct{ S1 } + +// A struct type embedding S2 +type StructEmbeddingS2 struct{ S2 } + +// A struct type embedding S1 and "overriding" its methods +type StructEmbeddingAndOverridingS1 struct{ S1 } + +func (t *StructEmbeddingAndOverridingS1) Source() interface{} { + return nil +} + +func (t *StructEmbeddingAndOverridingS1) Sink(interface{}) {} + +func (t *StructEmbeddingAndOverridingS1) Step(val interface{}) interface{} { + return val +} + +// A struct type embedding S2 and "overriding" its methods +type StructEmbeddingAndOverridingS2 struct{ S2 } + +func (t *StructEmbeddingAndOverridingS2) Source() interface{} { + return nil +} + +func (t *StructEmbeddingAndOverridingS2) Sink(interface{}) {} + +func (t *StructEmbeddingAndOverridingS2) Step(val interface{}) interface{} { + return val +} + +func (t *StructEmbeddingAndOverridingS2) ExtraMethod() {} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/modules.txt new file mode 100644 index 0000000000000..b62dbf8819b5a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/vendor/modules.txt @@ -0,0 +1,3 @@ +# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000 +## explicit +github.com/nonexistent/test