Create copy of ExternalTaintFlow called ExternalValueFlow

This commit is contained in:
Owen Mansel-Chan
2024-05-04 21:44:21 +01:00
parent 84b7319688
commit c816412795
16 changed files with 433 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
invalidModelRow
testFailures

View File

@@ -0,0 +1,40 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: summaryModel
data:
- ["github.com/nonexistent/test", "T", False, "StepArgRes", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepArgRes1", "", "", "Argument[0]", "ReturnValue[1]", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepArgArg", "", "", "Argument[0]", "Argument[1]", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepArgQual", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepQualRes", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepQualArg", "", "", "Argument[-1]", "Argument[0]", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgResNoQual", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgResArrayContent", "", "", "Argument[0]", "ReturnValue.ArrayElement", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgArrayContentRes", "", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgResCollectionContent", "", "", "Argument[0]", "ReturnValue.Element", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgCollectionContentRes", "", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgResMapKeyContent", "", "", "Argument[0]", "ReturnValue.MapKey", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgMapKeyContentRes", "", "", "Argument[0].MapKey", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgResMapValueContent", "", "", "Argument[0]", "ReturnValue.MapValue", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgMapValueContentRes", "", "", "Argument[0].MapValue", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "GetElement", "", "", "Argument[0].Element", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "", False, "GetMapKey", "", "", "Argument[0].MapKey", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "", False, "SetElement", "", "", "Argument[0]", "ReturnValue.Element", "value", "manual"]
- ["github.com/nonexistent/test", "C", False, "Get", "", "", "Argument[-1].Field[github.com/nonexistent/test.C.F]", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "C", False, "GetThroughPointer", "", "", "Argument[-1].Dereference.Field[github.com/nonexistent/test.C.F]", "ReturnValue", "value", "manual"]
- ["github.com/nonexistent/test", "C", False, "Set", "", "", "Argument[0]", "Argument[-1].Field[github.com/nonexistent/test.C.F]", "value", "manual"]
- ["github.com/nonexistent/test", "C", False, "SetThroughPointer", "", "", "Argument[0]", "Argument[-1].Dereference.Field[github.com/nonexistent/test.C.F]", "value", "manual"]
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/test", "A", False, "Src1", "", "", "ReturnValue", "qltest", "manual"]
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/nonexistent/test", "B", False, "Sink1", "", "", "Argument[0]", "qltest", "manual"]
- ["github.com/nonexistent/test", "B", False, "SinkManyArgs", "", "", "Argument[0..2]", "qltest", "manual"]

View File

@@ -0,0 +1,17 @@
/**
* @kind path-problem
*/
import go
import semmle.go.dataflow.ExternalFlow
import ModelValidation
import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
import TestUtilities.InlineFlowTest
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { sourceNode(src, "qltest") }
predicate isSink(DataFlow::Node src) { sinkNode(src, "qltest") }
}
import TaintFlowTest<Config>

View File

@@ -0,0 +1,5 @@
module semmle.go.Packages
go 1.13
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000

View File

@@ -0,0 +1,35 @@
invalidModelRow
#select
| test.go:47:10:47:12 | arg | qltest |
| test.go:48:2:48:13 | type assertion | qltest |
| test.go:61:10:61:15 | taint1 | qltest |
| test.go:64:10:64:15 | taint2 | qltest |
| test.go:68:10:68:15 | taint3 | qltest |
| test.go:72:10:72:15 | taint4 | qltest |
| test.go:75:10:75:15 | taint5 | qltest |
| test.go:79:10:79:15 | taint6 | qltest |
| test.go:82:10:82:15 | taint7 | qltest |
| test.go:85:10:85:18 | index expression | qltest |
| test.go:89:10:89:15 | taint9 | qltest |
| test.go:92:10:92:33 | call to GetElement | qltest |
| test.go:93:10:93:18 | <-... | qltest |
| test.go:97:10:97:16 | taint11 | qltest |
| test.go:100:10:100:32 | call to GetMapKey | qltest |
| test.go:102:11:102:11 | k | qltest |
| test.go:105:11:105:11 | k | qltest |
| test.go:110:10:110:16 | taint13 | qltest |
| test.go:113:10:113:20 | index expression | qltest |
| test.go:117:10:117:16 | taint15 | qltest |
| test.go:121:10:121:17 | index expression | qltest |
| test.go:126:10:126:16 | taint16 | qltest |
| test.go:130:10:130:13 | selection of F | qltest |
| test.go:133:10:133:17 | call to Get | qltest |
| test.go:137:10:137:17 | call to Get | qltest |
| test.go:142:10:142:17 | call to Get | qltest |
| test.go:146:10:146:14 | selection of F | qltest |
| test.go:149:10:149:32 | call to GetThroughPointer | qltest |
| test.go:153:10:153:32 | call to GetThroughPointer | qltest |
| test.go:158:10:158:32 | call to GetThroughPointer | qltest |
| test.go:164:17:164:20 | arg1 | qltest |
| test.go:164:23:164:26 | arg2 | qltest |
| test.go:164:29:164:32 | arg3 | qltest |

View File

@@ -0,0 +1,8 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/nonexistent/test", "B", False, "Sink1", "", "", "Argument[0]", "qltest", "manual"]
- ["github.com/nonexistent/test", "B", False, "SinkMethod", "", "", "Argument[-1]", "qltest", "manual"]
- ["github.com/nonexistent/test", "B", False, "SinkManyArgs", "", "", "Argument[0..2]", "qltest", "manual"]

View File

@@ -0,0 +1,7 @@
import go
import semmle.go.dataflow.ExternalFlow
import ModelValidation
from DataFlow::Node node, string kind
where sinkNode(node, kind)
select node, kind

View File

@@ -0,0 +1,23 @@
invalidModelRow
#select
| test.go:10:6:10:8 | definition of arg | qltest-arg |
| test.go:38:8:38:15 | call to Src1 | qltest |
| test.go:39:8:39:15 | call to Src2 | qltest |
| test.go:39:8:39:15 | call to Src2 | qltest-w-subtypes |
| test.go:40:8:40:16 | call to Src2 | qltest-w-subtypes |
| test.go:41:2:41:21 | ... = ...[0] | qltest |
| test.go:41:2:41:21 | ... = ...[1] | qltest-w-subtypes |
| test.go:42:2:42:22 | ... = ...[1] | qltest-w-subtypes |
| test.go:58:9:58:16 | call to Src1 | qltest |
| test.go:91:46:91:53 | call to Src1 | qltest |
| test.go:95:35:95:42 | call to Src1 | qltest |
| test.go:99:42:99:49 | call to Src1 | qltest |
| test.go:124:8:124:15 | call to Src1 | qltest |
| test.go:129:9:129:16 | call to Src1 | qltest |
| test.go:132:15:132:22 | call to Src1 | qltest |
| test.go:136:9:136:16 | call to Src1 | qltest |
| test.go:140:9:140:16 | call to Src1 | qltest |
| test.go:145:24:145:31 | call to Src1 | qltest |
| test.go:148:17:148:24 | call to Src1 | qltest |
| test.go:152:24:152:31 | call to Src1 | qltest |
| test.go:156:24:156:31 | call to Src1 | qltest |

View File

@@ -0,0 +1,11 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/test", "A", False, "Src1", "", "", "ReturnValue", "qltest", "manual"]
- ["github.com/nonexistent/test", "A", False, "Src2", "", "", "ReturnValue", "qltest", "manual"]
- ["github.com/nonexistent/test", "A", True, "Src2", "", "", "ReturnValue", "qltest-w-subtypes", "manual"]
- ["github.com/nonexistent/test", "A", False, "SrcArg", "", "", "Argument[0]", "qltest-arg", "manual"]
- ["github.com/nonexistent/test", "A", False, "Src3", "", "", "ReturnValue[0]", "qltest", "manual"]
- ["github.com/nonexistent/test", "A", True, "Src3", "", "", "ReturnValue[1]", "qltest-w-subtypes", "manual"]

View File

@@ -0,0 +1,7 @@
import go
import semmle.go.dataflow.ExternalFlow
import ModelValidation
from DataFlow::Node node, string kind
where sourceNode(node, kind)
select node, kind

View File

@@ -0,0 +1,16 @@
invalidModelRow
#select
| test.go:17:23:17:25 | arg | test.go:17:10:17:26 | call to StepArgRes |
| test.go:18:27:18:29 | arg | test.go:18:2:18:30 | ... = ...[1] |
| test.go:19:15:19:17 | arg | test.go:11:6:11:9 | definition of arg1 |
| test.go:20:16:20:18 | arg | test.go:13:6:13:6 | definition of t |
| test.go:21:10:21:10 | t | test.go:21:10:21:24 | call to StepQualRes |
| test.go:22:2:22:2 | t | test.go:10:6:10:8 | definition of arg |
| test.go:23:32:23:34 | arg | test.go:23:10:23:35 | call to StepArgResNoQual |
| test.go:60:25:60:27 | src | test.go:60:12:60:28 | call to StepArgRes |
| test.go:63:29:63:31 | src | test.go:63:2:63:32 | ... := ...[1] |
| test.go:67:15:67:17 | src | test.go:66:6:66:11 | definition of taint3 |
| test.go:71:21:71:23 | src | test.go:70:6:70:11 | definition of taint4 |
| test.go:74:13:74:25 | type assertion | test.go:74:12:74:40 | call to StepQualRes |
| test.go:78:3:78:15 | type assertion | test.go:77:6:77:11 | definition of taint6 |
| test.go:81:34:81:36 | src | test.go:81:12:81:37 | call to StepArgResNoQual |

View File

@@ -0,0 +1,14 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: summaryModel
data:
- ["github.com/nonexistent/test", "T", False, "StepArgRes", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepArgRes1", "", "", "Argument[0]", "ReturnValue[1]", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepArgArg", "", "", "Argument[0]", "Argument[1]", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepArgQual", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepQualRes", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "T", False, "StepQualArg", "", "", "Argument[-1]", "Argument[0]", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgResNoQual", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgResContent", "", "", "Argument[0]", "ReturnValue.ArrayElement", "taint", "manual"]
- ["github.com/nonexistent/test", "", False, "StepArgContentRes", "", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"]

View File

@@ -0,0 +1,8 @@
import go
import semmle.go.dataflow.ExternalFlow
import ModelValidation
import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
from DataFlow::Node node1, DataFlow::Node node2
where FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(node1, node2, _)
select node1, node2

View File

@@ -0,0 +1,165 @@
package main
import (
"github.com/nonexistent/test"
)
func use(args ...interface{}) {}
func main() {
var arg interface{}
var arg1 interface{}
var array []interface{}
var t *test.T
var taint interface{}
var taintSlice []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)
taintSlice = test.StepArgResArrayContent(arg)
taint = test.StepArgArrayContentRes(array)
taint = test.StepArgResCollectionContent(arg)
taint = test.StepArgCollectionContentRes(array)
taint = test.StepArgResMapKeyContent(arg)
taint = test.StepArgMapKeyContentRes(array)
taint = test.StepArgResMapValueContent(arg)
taint = test.StepArgMapValueContentRes(array)
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)
arg.(test.B).SinkMethod()
use(arg, arg1, t, taint, taintSlice, src, src1)
}
func simpleflow() {
var a test.A
var b test.B
var t *test.T
src := a.Src1()
taint1 := t.StepArgRes(src)
b.Sink1(taint1) // $ hasTaintFlow="taint1"
_, taint2 := t.StepArgRes1(src)
b.Sink1(taint2) // $ hasTaintFlow="taint2"
var taint3 interface{}
t.StepArgArg(src, taint3)
b.Sink1(taint3) // $ hasTaintFlow="taint3"
var taint4 test.T
taint4.StepArgQual(src)
b.Sink1(taint4) // $ hasTaintFlow="taint4"
taint5 := (src.(*test.T)).StepQualRes()
b.Sink1(taint5) // $ hasTaintFlow="taint5"
var taint6 interface{}
(src.(*test.T)).StepQualArg(taint6)
b.Sink1(taint6) // $ hasTaintFlow="taint6"
taint7 := test.StepArgResNoQual(src)
b.Sink1(taint7) // $ hasTaintFlow="taint7"
taint8 := test.StepArgResArrayContent(src)
b.Sink1(taint8[0]) // $ hasTaintFlow="index expression"
srcArray := []interface{}{nil, src}
taint9 := test.StepArgArrayContentRes(srcArray)
b.Sink1(taint9) // $ hasTaintFlow="taint9"
taint10 := test.StepArgResCollectionContent(a.Src1()).(chan interface{})
b.Sink1(test.GetElement(taint10)) // $ hasTaintFlow="call to GetElement"
b.Sink1(<-taint10) // $ hasTaintFlow="<-..."
srcCollection := test.SetElement(a.Src1())
taint11 := test.StepArgCollectionContentRes(srcCollection)
b.Sink1(taint11) // $ hasTaintFlow="taint11"
taint12 := test.StepArgResMapKeyContent(a.Src1()).(map[string]string)
b.Sink1(test.GetMapKey(taint12)) // $ hasTaintFlow="call to GetMapKey"
for k, _ := range taint12 {
b.Sink1(k) // $ hasTaintFlow="k"
}
for k := range taint12 {
b.Sink1(k) // $ hasTaintFlow="k"
}
srcMap13 := map[string]string{src.(string): ""}
taint13 := test.StepArgMapKeyContentRes(srcMap13)
b.Sink1(taint13) // $ hasTaintFlow="taint13"
taint14 := test.StepArgResMapValueContent(src).(map[string]string)
b.Sink1(taint14[""]) // $ hasTaintFlow="index expression"
srcMap15 := map[string]string{"": src.(string)}
taint15 := test.StepArgMapValueContentRes(srcMap15)
b.Sink1(taint15) // $ hasTaintFlow="taint15"
slice := make([]interface{}, 0)
slice = append(slice, src)
b.Sink1(slice[0]) // $ hasTaintFlow="index expression"
ch := make(chan string)
ch <- a.Src1().(string)
taint16 := test.StepArgCollectionContentRes(ch)
b.Sink1(taint16) // $ MISSING: hasTaintFlow="taint16" // currently fails due to lack of post-update nodes after send statements
c1 := test.C{""}
c1.Set(a.Src1().(string))
b.Sink1(c1.F) // $ hasTaintFlow="selection of F"
c2 := test.C{a.Src1().(string)}
b.Sink1(c2.Get()) // $ hasTaintFlow="call to Get"
c3 := test.C{""}
c3.Set(a.Src1().(string))
b.Sink1(c3.Get()) // $ hasTaintFlow="call to Get"
c4 := test.C{""}
c4.Set(a.Src1().(string))
c4.Set("")
b.Sink1(c4.Get()) // $ SPURIOUS: hasTaintFlow="call to Get" // because we currently don't clear content
cp1 := &test.C{""}
cp1.SetThroughPointer(a.Src1().(string))
b.Sink1(cp1.F) // $ hasTaintFlow="selection of F"
cp2 := &test.C{a.Src1().(string)}
b.Sink1(cp2.GetThroughPointer()) // $ hasTaintFlow="call to GetThroughPointer"
cp3 := &test.C{""}
cp3.SetThroughPointer(a.Src1().(string))
b.Sink1(cp3.GetThroughPointer()) // $ hasTaintFlow="call to GetThroughPointer"
cp4 := &test.C{""}
cp4.SetThroughPointer(a.Src1().(string))
cp4.SetThroughPointer("")
b.Sink1(cp4.GetThroughPointer()) // $ SPURIOUS: hasTaintFlow="call to GetThroughPointer" // because we currently don't clear content
arg1 := src
arg2 := src
arg3 := src
arg4 := src
b.SinkManyArgs(arg1, arg2, arg3, arg4) // $ hasTaintFlow="arg1" hasTaintFlow="arg2" hasTaintFlow="arg3"
}

View File

@@ -0,0 +1,72 @@
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 StepArgResArrayContent(arg interface{}) []interface{} { return nil }
func StepArgArrayContentRes(arg []interface{}) interface{} { return nil }
func StepArgResCollectionContent(arg interface{}) interface{} { return nil }
func StepArgCollectionContentRes(arg interface{}) interface{} { return nil }
func StepArgResMapKeyContent(arg interface{}) interface{} { return nil }
func StepArgMapKeyContentRes(arg interface{}) interface{} { return nil }
func StepArgResMapValueContent(arg interface{}) interface{} { return nil }
func StepArgMapValueContentRes(arg interface{}) interface{} { return nil }
func GetElement(x interface{}) interface{} { return nil }
func SetElement(x interface{}) interface{} { return nil }
func GetMapKey(x 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{}
SinkManyArgs(arg1 interface{}, arg2 interface{}, arg3 interface{}, arg4 interface{})
}
type C struct {
F string
}
func (c C) Set(f string) {}
func (c C) Get() string { return "" }
func (c *C) SetThroughPointer(f string) {}
func (c *C) GetThroughPointer() string { return "" }

View File

@@ -0,0 +1,3 @@
# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
## explicit
github.com/nonexistent/test