mirror of
https://github.com/github/codeql.git
synced 2026-01-29 22:32:58 +01:00
Add variadic functions test for function models
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
invalidModelRow
|
||||
@@ -0,0 +1,96 @@
|
||||
import go
|
||||
import semmle.go.dataflow.ExternalFlow
|
||||
import CsvValidation
|
||||
// import DataFlow::PartialPathGraph
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class SummaryModelTest extends DataFlow::FunctionModel {
|
||||
FunctionInput inp;
|
||||
FunctionOutput outp;
|
||||
|
||||
SummaryModelTest() {
|
||||
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithParameter") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// Cannot model this correctly for data flow, but it should work for taint flow
|
||||
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithSliceParameter") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsParameter") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
// or
|
||||
// this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithSliceOfStructsParameter")) and
|
||||
// (inp.isParameter(0) and outp.isResult)
|
||||
// or
|
||||
// this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsOfStructsParameter")) and
|
||||
// (inp.isParameter(0) and outp.isResult)
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input = inp and output = outp
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
override int explorationLimit() { result = 10 } // this is different!
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
override int explorationLimit() { result = 10 } // this is different!
|
||||
}
|
||||
|
||||
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, _, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
// from TaintConfiguration cfg, DataFlow::PartialPathNode source, DataFlow::PartialPathNode sink
|
||||
// where
|
||||
// cfg.hasPartialFlow(source, sink, _)
|
||||
// and
|
||||
// source.getNode().hasLocationInfo(_, 22, _, _, _)
|
||||
// select sink, source, sink, "Partial flow from unsanitized user data"
|
||||
@@ -0,0 +1,5 @@
|
||||
module semmle.go.Packages
|
||||
|
||||
go 1.17
|
||||
|
||||
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
|
||||
@@ -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 MISSING: dataflow
|
||||
sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ taintflow MISSING: 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)) // $ MISSING: taintflow dataflow
|
||||
sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ MISSING: taintflow dataflow
|
||||
sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ MISSING: taintflow dataflow
|
||||
}
|
||||
Binary file not shown.
25
ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/vendor/github.com/nonexistent/test/stub.go
generated
vendored
Normal file
25
ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/vendor/github.com/nonexistent/test/stub.go
generated
vendored
Normal file
@@ -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 ""
|
||||
}
|
||||
3
ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/vendor/modules.txt
vendored
Normal file
3
ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/vendor/modules.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
|
||||
## explicit
|
||||
github.com/nonexistent/test
|
||||
Reference in New Issue
Block a user