Skip to content

Commit f375553

Browse files
committed
Add variadic functions test for function models
1 parent b75def6 commit f375553

File tree

7 files changed

+169
-0
lines changed

7 files changed

+169
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
failures
2+
invalidModelRow
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import go
2+
import semmle.go.dataflow.ExternalFlow
3+
import CsvValidation
4+
// import DataFlow::PartialPathGraph
5+
import TestUtilities.InlineExpectationsTest
6+
7+
class SummaryModelTest extends DataFlow::FunctionModel {
8+
FunctionInput inp;
9+
FunctionOutput outp;
10+
11+
SummaryModelTest() {
12+
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithParameter") and
13+
(inp.isParameter(0) and outp.isResult())
14+
or
15+
// Cannot model this correctly for data flow, but it should work for taint flow
16+
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithSliceParameter") and
17+
(inp.isParameter(0) and outp.isResult())
18+
or
19+
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsParameter") and
20+
(inp.isParameter(_) and outp.isResult())
21+
// or
22+
// this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithSliceOfStructsParameter")) and
23+
// (inp.isParameter(0) and outp.isResult)
24+
// or
25+
// this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsOfStructsParameter")) and
26+
// (inp.isParameter(0) and outp.isResult)
27+
}
28+
29+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
30+
input = inp and output = outp
31+
}
32+
}
33+
34+
class DataConfiguration extends DataFlow::Configuration {
35+
DataConfiguration() { this = "data-configuration" }
36+
37+
override predicate isSource(DataFlow::Node source) {
38+
source = any(DataFlow::CallNode c | c.getCalleeName() = "source").getResult(0)
39+
}
40+
41+
override predicate isSink(DataFlow::Node sink) {
42+
sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0)
43+
}
44+
45+
override int explorationLimit() { result = 10 } // this is different!
46+
}
47+
48+
class DataFlowTest extends InlineExpectationsTest {
49+
DataFlowTest() { this = "DataFlowTest" }
50+
51+
override string getARelevantTag() { result = "dataflow" }
52+
53+
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
54+
tag = "dataflow" and
55+
exists(DataFlow::Node sink | any(DataConfiguration c).hasFlow(_, sink) |
56+
element = sink.toString() and
57+
value = "" and
58+
sink.hasLocationInfo(file, line, _, _, _)
59+
)
60+
}
61+
}
62+
63+
class TaintConfiguration extends TaintTracking::Configuration {
64+
TaintConfiguration() { this = "taint-configuration" }
65+
66+
override predicate isSource(DataFlow::Node source) {
67+
source = any(DataFlow::CallNode c | c.getCalleeName() = "source").getResult(0)
68+
}
69+
70+
override predicate isSink(DataFlow::Node sink) {
71+
sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0)
72+
}
73+
74+
override int explorationLimit() { result = 10 } // this is different!
75+
}
76+
77+
class TaintFlowTest extends InlineExpectationsTest {
78+
TaintFlowTest() { this = "TaintFlowTest" }
79+
80+
override string getARelevantTag() { result = "taintflow" }
81+
82+
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
83+
tag = "taintflow" and
84+
exists(DataFlow::Node sink | any(TaintConfiguration c).hasFlow(_, sink) |
85+
element = sink.toString() and
86+
value = "" and
87+
sink.hasLocationInfo(file, line, _, _, _)
88+
)
89+
}
90+
}
91+
// from TaintConfiguration cfg, DataFlow::PartialPathNode source, DataFlow::PartialPathNode sink
92+
// where
93+
// cfg.hasPartialFlow(source, sink, _)
94+
// and
95+
// source.getNode().hasLocationInfo(_, 22, _, _, _)
96+
// select sink, source, sink, "Partial flow from unsanitized user data"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module semmle.go.Packages
2+
3+
go 1.17
4+
5+
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package main
2+
3+
import (
4+
"github.com/nonexistent/test"
5+
)
6+
7+
func source() string {
8+
return "untrusted data"
9+
}
10+
11+
func sink(string) {
12+
}
13+
14+
func main() {
15+
s := source()
16+
sink(test.FunctionWithParameter(s)) // $ taintflow dataflow
17+
18+
stringSlice := []string{source()}
19+
sink(stringSlice[0]) // $ taintflow dataflow
20+
21+
s0 := ""
22+
s1 := source()
23+
sSlice := []string{s0, s1}
24+
sink(test.FunctionWithParameter(sSlice[1])) // $ taintflow dataflow
25+
sink(test.FunctionWithSliceParameter(sSlice)) // $ taintflow MISSING: dataflow
26+
sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ taintflow MISSING: dataflow
27+
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ MISSING: taintflow dataflow
28+
29+
sliceOfStructs := []test.A{{Field: source()}}
30+
sink(sliceOfStructs[0].Field) // $ taintflow dataflow
31+
32+
a0 := test.A{Field: ""}
33+
a1 := test.A{Field: source()}
34+
aSlice := []test.A{a0, a1}
35+
sink(test.FunctionWithSliceOfStructsParameter(aSlice)) // $ MISSING: taintflow dataflow
36+
sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ MISSING: taintflow dataflow
37+
sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ MISSING: taintflow dataflow
38+
}
Binary file not shown.

ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/vendor/github.com/nonexistent/test/stub.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
2+
## explicit
3+
github.com/nonexistent/test

0 commit comments

Comments
 (0)