Implement standard library models for Go 1.20

This commit is contained in:
Chris Smowton
2023-02-15 18:29:49 +00:00
parent 7d2b78b463
commit 7e7850374e
9 changed files with 216 additions and 0 deletions

View File

@@ -65,6 +65,7 @@ import semmle.go.frameworks.stdlib.Syscall
import semmle.go.frameworks.stdlib.TextScanner
import semmle.go.frameworks.stdlib.TextTabwriter
import semmle.go.frameworks.stdlib.TextTemplate
import semmle.go.frameworks.stdlib.Unsafe
/** A `String()` method. */
class StringMethod extends TaintTracking::FunctionModel, Method {

View File

@@ -11,6 +11,15 @@ module Bytes {
FunctionOutput outp;
FunctionModels() {
hasQualifiedName("bytes", "Clone") and
(inp.isParameter(0) and outp.isResult())
or
hasQualifiedName("bytes", "Cut") and
(inp.isParameter(0) and outp.isResult([0, 1]))
or
hasQualifiedName("bytes", ["CutPrefix", "CutSuffix"]) and
(inp.isParameter(0) and outp.isResult(0))
or
// signature: func Fields(s []byte) [][]byte
hasQualifiedName("bytes", "Fields") and
(inp.isParameter(0) and outp.isResult())

View File

@@ -22,6 +22,10 @@ module Errors {
// signature: func Unwrap(err error) error
hasQualifiedName("errors", "Unwrap") and
(inp.isParameter(0) and outp.isResult())
or
// signature: func Join(errs ...error) error
hasQualifiedName("errors", "Join") and
(inp.isParameter(_) and outp.isResult())
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {

View File

@@ -11,6 +11,9 @@ module Sync {
FunctionOutput outp;
MethodModels() {
hasQualifiedName("sync", "Map", "CompareAndSwap") and
(inp.isParameter(2) and outp.isReceiver())
or
// signature: func (*Map) Load(key interface{}) (value interface{}, ok bool)
hasQualifiedName("sync", "Map", "Load") and
(inp.isReceiver() and outp.isResult(0))
@@ -28,6 +31,13 @@ module Sync {
hasQualifiedName("sync", "Map", "Store") and
(inp.isParameter(_) and outp.isReceiver())
or
hasQualifiedName("sync", "Map", "Swap") and
(
inp.isReceiver() and outp.isResult(0)
or
inp.isParameter(_) and outp.isReceiver()
)
or
// signature: func (*Pool) Get() interface{}
hasQualifiedName("sync", "Pool", "Get") and
(inp.isReceiver() and outp.isResult())

View File

@@ -0,0 +1,22 @@
/**
* Provides classes modeling security-relevant aspects of the `unsafe` package.
*/
import go
/** Provides models of commonly used functions in the `unsafe` package. */
module Unsafe {
private class FunctionModels extends TaintTracking::FunctionModel {
FunctionInput inp;
FunctionOutput outp;
FunctionModels() {
hasQualifiedName("unsafe", ["String", "StringData", "Slice", "SliceData"]) and
(inp.isParameter(0) and outp.isResult())
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
}

View File

@@ -316,6 +316,39 @@ func TaintStepTest_BytesReaderWriteTo_B0I0O0(sourceCQL interface{}) interface{}
return intoWriter197
}
func TaintStepTest_Clone(sourceCQL interface{}) interface{} {
fromReader628 := sourceCQL.([]byte)
return bytes.Clone(fromReader628)
}
func TaintStepTest_Cutleft(sourceCQL interface{}) interface{} {
fromReader628 := sourceCQL.([]byte)
sep := []byte{}
left, _, _ := bytes.Cut(fromReader628, sep)
return left
}
func TaintStepTest_Cutright(sourceCQL interface{}) interface{} {
fromReader628 := sourceCQL.([]byte)
sep := []byte{}
_, right, _ := bytes.Cut(fromReader628, sep)
return right
}
func TaintStepTest_CutPrefix(sourceCQL interface{}) interface{} {
fromReader628 := sourceCQL.([]byte)
sep := []byte{}
result, _ := bytes.CutPrefix(fromReader628, sep)
return result
}
func TaintStepTest_CutSuffix(sourceCQL interface{}) interface{} {
fromReader628 := sourceCQL.([]byte)
sep := []byte{}
result, _ := bytes.CutSuffix(fromReader628, sep)
return result
}
func RunAllTaints_Bytes() {
{
source := newSource(0)
@@ -567,4 +600,29 @@ func RunAllTaints_Bytes() {
out := TaintStepTest_BytesReaderWriteTo_B0I0O0(source)
sink(49, out)
}
{
source := newSource(50)
out := TaintStepTest_Cutleft(source)
sink(50, out)
}
{
source := newSource(51)
out := TaintStepTest_Cutright(source)
sink(51, out)
}
{
source := newSource(52)
out := TaintStepTest_CutPrefix(source)
sink(52, out)
}
{
source := newSource(53)
out := TaintStepTest_CutSuffix(source)
sink(53, out)
}
{
source := newSource(54)
out := TaintStepTest_Clone(source)
sink(54, out)
}
}

View File

@@ -23,6 +23,18 @@ func TaintStepTest_ErrorsUnwrap_B0I0O0(sourceCQL interface{}) interface{} {
return intoError957
}
func TaintStepTest_ErrorsJoin1(sourceCQL interface{}) interface{} {
fromError784 := sourceCQL.(error)
intoError957 := errors.Join(fromError784, errors.New(""))
return intoError957
}
func TaintStepTest_ErrorsJoin2(sourceCQL interface{}) interface{} {
fromError784 := sourceCQL.(error)
intoError957 := errors.Join(errors.New(""), fromError784)
return intoError957
}
func RunAllTaints_Errors() {
{
source := newSource(0)
@@ -39,4 +51,14 @@ func RunAllTaints_Errors() {
out := TaintStepTest_ErrorsUnwrap_B0I0O0(source)
sink(2, out)
}
{
source := newSource(3)
out := TaintStepTest_ErrorsJoin1(source)
sink(3, out)
}
{
source := newSource(4)
out := TaintStepTest_ErrorsJoin2(source)
sink(4, out)
}
}

View File

@@ -58,6 +58,30 @@ func TaintStepTest_SyncMapStore_B0I1O0(sourceCQL interface{}) interface{} {
return intoMap881
}
func TaintStepTest_SyncMapSwapinkey(sourceCQL interface{}) interface{} {
var m sync.Map
m.Swap(sourceCQL, "value")
return m
}
func TaintStepTest_SyncMapSwapinvalue(sourceCQL interface{}) interface{} {
var m sync.Map
m.Swap("key", sourceCQL)
return m
}
func TaintStepTest_SyncMapSwapout(sourceCQL interface{}) interface{} {
m := sourceCQL.(sync.Map)
oldVal, _ := m.Swap("key", "value")
return oldVal
}
func TaintStepTest_SyncMapCompareAndSwap(sourceCQL interface{}) interface{} {
var m sync.Map
m.CompareAndSwap("key", "compareTo", sourceCQL)
return m
}
func TaintStepTest_SyncPoolGet_B0I0O0(sourceCQL interface{}) interface{} {
fromPool186 := sourceCQL.(sync.Pool)
intoInterface284 := fromPool186.Get()
@@ -122,4 +146,24 @@ func RunAllTaints_Sync() {
out := TaintStepTest_SyncPoolPut_B0I0O0(source)
sink(9, out)
}
{
source := newSource(10)
out := TaintStepTest_SyncMapSwapinkey(source)
sink(10, out)
}
{
source := newSource(11)
out := TaintStepTest_SyncMapSwapinvalue(source)
sink(11, out)
}
{
source := newSource(12)
out := TaintStepTest_SyncMapSwapout(source)
sink(12, out)
}
{
source := newSource(13)
out := TaintStepTest_SyncMapCompareAndSwap(source)
sink(13, out)
}
}

View File

@@ -0,0 +1,46 @@
package main
import "unsafe"
func TaintStepTest_UnsafeSlice(sourceCQL interface{}) interface{} {
s := sourceCQL.(*byte)
return unsafe.Slice(s, 1)
}
func TaintStepTest_UnsafeSliceData(sourceCQL interface{}) interface{} {
s := sourceCQL.([]byte)
return unsafe.SliceData(s)
}
func TaintStepTest_UnsafeString(sourceCQL interface{}) interface{} {
s := sourceCQL.(*byte)
return unsafe.String(s, 1)
}
func TaintStepTest_UnsafeStringData(sourceCQL interface{}) interface{} {
s := sourceCQL.(string)
return unsafe.StringData(s)
}
func RunAllTaints_Sync() {
{
source := newSource(0)
out := TaintStepTest_UnsafeSlice(source)
sink(0, out)
}
{
source := newSource(1)
out := TaintStepTest_UnsafeSliceData(source)
sink(1, out)
}
{
source := newSource(2)
out := TaintStepTest_UnsafeString(source)
sink(2, out)
}
{
source := newSource(3)
out := TaintStepTest_UnsafeStringData(source)
sink(3, out)
}
}