Add models for gopkg.in/yaml

This commit is contained in:
Sauyon Lee
2021-02-10 23:34:00 +00:00
parent a2c0b6ade6
commit 1acbfaafcc
11 changed files with 336 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Added support for the [gopkg.in/yaml](https://pkg.go.dev/gopkg.in/yaml.v3) package, which may lead to more results from the security queries.

View File

@@ -58,5 +58,6 @@ import semmle.go.frameworks.Testing
import semmle.go.frameworks.WebSocket
import semmle.go.frameworks.XNetHtml
import semmle.go.frameworks.XPath
import semmle.go.frameworks.Yaml
import semmle.go.frameworks.Zap
import semmle.go.security.FlowSources

View File

@@ -0,0 +1,70 @@
/**
* Provides classes for working with the [gopkg.in/yaml](https://pkg.go.dev/gopkg.in/yaml.v3) package.
*/
import go
/**
* Provides classes for working with the [gopkg.in/yaml](https://pkg.go.dev/gopkg.in/yaml.v3) package.
*/
module Yaml {
/** Gets a package path for the Yaml package. */
bindingset[result]
string packagePath() { result = package("gopkg.in/yaml", "") }
private class MarshalFunction extends TaintTracking::FunctionModel, MarshalingFunction::Range {
MarshalFunction() { this.hasQualifiedName(packagePath(), "Marshal") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = this.getAnInput() and output = this.getOutput()
}
override DataFlow::FunctionInput getAnInput() { result.isParameter(0) }
override DataFlow::FunctionOutput getOutput() { result.isResult(0) }
override string getFormat() { result = "yaml" }
}
private class UnmarshalFunction extends TaintTracking::FunctionModel, UnmarshalingFunction::Range {
UnmarshalFunction() { this.hasQualifiedName(packagePath(), ["Unmarshal", "UnmarshalStrict"]) }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = this.getAnInput() and output = this.getOutput()
}
override DataFlow::FunctionInput getAnInput() { result.isParameter(0) }
override DataFlow::FunctionOutput getOutput() { result.isParameter(1) }
override string getFormat() { result = "yaml" }
}
private class FunctionModels extends TaintTracking::FunctionModel {
FunctionInput inp;
FunctionOutput outp;
FunctionModels() {
this.hasQualifiedName(packagePath(), "NewDecoder") and
(inp.isParameter(0) and outp.isResult())
or
this.hasQualifiedName(packagePath(), "NewEncoder") and
(inp.isResult() and outp.isParameter(0))
or
exists(Method m | this = m |
m.hasQualifiedName(packagePath(), ["Decoder", "Node"], "Decode") and
(inp.isReceiver() and outp.isParameter(0))
or
m.hasQualifiedName(packagePath(), ["Encoder", "Node"], "Encode") and
(inp.isParameter(0) and outp.isReceiver())
or
m.hasQualifiedName(packagePath(), "Node", "SetString") and
(inp.isParameter(0) and outp.isReceiver())
)
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
}

View File

@@ -0,0 +1,9 @@
module codeql-go-tests/frameworks/Yaml
go 1.15
require (
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

View File

@@ -0,0 +1,49 @@
import go
import TestUtilities.InlineExpectationsTest
class TaintFunctionModelTest extends InlineExpectationsTest {
TaintFunctionModelTest() { this = "TaintFunctionModelTest" }
override string getARelevantTag() { result = "ttfnmodelstep" }
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
tag = "ttfnmodelstep" and
exists(TaintTracking::FunctionModel model, DataFlow::CallNode call | call = model.getACall() |
call.hasLocationInfo(file, line, _, _, _) and
element = call.toString() and
value = model.getAnInputNode(call) + " -> " + model.getAnOutputNode(call)
)
}
}
class MarshalerTest extends InlineExpectationsTest {
MarshalerTest() { this = "MarshalerTest" }
override string getARelevantTag() { result = "marshaler" }
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
tag = "marshaler" and
exists(MarshalingFunction m, DataFlow::CallNode call | call = m.getACall() |
call.hasLocationInfo(file, line, _, _, _) and
element = call.toString() and
value =
m.getFormat() + ": " + m.getAnInput().getNode(call) + " -> " + m.getOutput().getNode(call)
)
}
}
class UnmarshalerTest extends InlineExpectationsTest {
UnmarshalerTest() { this = "UnmarshalerTest" }
override string getARelevantTag() { result = "unmarshaler" }
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
tag = "unmarshaler" and
exists(UnmarshalingFunction m, DataFlow::CallNode call | call = m.getACall() |
call.hasLocationInfo(file, line, _, _, _) and
element = call.toString() and
value =
m.getFormat() + ": " + m.getAnInput().getNode(call) + " -> " + m.getOutput().getNode(call)
)
}
}

View File

@@ -0,0 +1,16 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for gopkg.in/yaml.v1, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: gopkg.in/yaml.v1 (exports: ; functions: Marshal,Unmarshal)
// Package yaml is a stub of gopkg.in/yaml.v1, generated by depstubber.
package yaml
func Marshal(_ interface{}) ([]byte, error) {
return nil, nil
}
func Unmarshal(_ []byte, _ interface{}) error {
return nil
}

View File

@@ -0,0 +1,50 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for gopkg.in/yaml.v2, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: gopkg.in/yaml.v2 (exports: ; functions: Marshal,NewDecoder,NewEncoder,Unmarshal,UnmarshalStrict)
// Package yaml is a stub of gopkg.in/yaml.v2, generated by depstubber.
package yaml
import (
io "io"
)
type Decoder struct{}
func (_ *Decoder) Decode(_ interface{}) error {
return nil
}
func (_ *Decoder) SetStrict(_ bool) {}
type Encoder struct{}
func (_ *Encoder) Close() error {
return nil
}
func (_ *Encoder) Encode(_ interface{}) error {
return nil
}
func Marshal(_ interface{}) ([]byte, error) {
return nil, nil
}
func NewDecoder(_ io.Reader) *Decoder {
return nil
}
func NewEncoder(_ io.Writer) *Encoder {
return nil
}
func Unmarshal(_ []byte, _ interface{}) error {
return nil
}
func UnmarshalStrict(_ []byte, _ interface{}) error {
return nil
}

View File

@@ -0,0 +1,89 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for gopkg.in/yaml.v3, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: gopkg.in/yaml.v3 (exports: Node; functions: Marshal,NewDecoder,NewEncoder,Unmarshal)
// Package yaml is a stub of gopkg.in/yaml.v3, generated by depstubber.
package yaml
import (
io "io"
)
type Decoder struct{}
func (_ *Decoder) Decode(_ interface{}) error {
return nil
}
func (_ *Decoder) KnownFields(_ bool) {}
type Encoder struct{}
func (_ *Encoder) Close() error {
return nil
}
func (_ *Encoder) Encode(_ interface{}) error {
return nil
}
func (_ *Encoder) SetIndent(_ int) {}
type Kind uint32
func Marshal(_ interface{}) ([]byte, error) {
return nil, nil
}
func NewDecoder(_ io.Reader) *Decoder {
return nil
}
func NewEncoder(_ io.Writer) *Encoder {
return nil
}
type Node struct {
Kind Kind
Style Style
Tag string
Value string
Anchor string
Alias *Node
Content []*Node
HeadComment string
LineComment string
FootComment string
Line int
Column int
}
func (_ *Node) Decode(_ interface{}) error {
return nil
}
func (_ *Node) Encode(_ interface{}) error {
return nil
}
func (_ *Node) IsZero() bool {
return false
}
func (_ *Node) LongTag() string {
return ""
}
func (_ *Node) SetString(_ string) {}
func (_ *Node) ShortTag() string {
return ""
}
type Style uint32
func Unmarshal(_ []byte, _ interface{}) error {
return nil
}

View File

@@ -0,0 +1,9 @@
# gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0
## explicit
gopkg.in/yaml.v1
# gopkg.in/yaml.v2 v2.4.0
## explicit
gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
## explicit
gopkg.in/yaml.v3

View File

@@ -0,0 +1,41 @@
package main
import (
yaml1 "gopkg.in/yaml.v1"
yaml2 "gopkg.in/yaml.v2"
yaml3 "gopkg.in/yaml.v3"
"io"
)
func main() {
var in, out interface{}
var inb []byte
out, _ = yaml1.Marshal(in) // $marshaler=yaml: in -> ... = ...[0] $ttfnmodelstep=in -> ... = ...[0]
yaml1.Unmarshal(inb, out) // $unmarshaler=yaml: inb -> definition of out $ttfnmodelstep=inb -> definition of out
out, _ = yaml2.Marshal(in) // $marshaler=yaml: in -> ... = ...[0] $ttfnmodelstep=in -> ... = ...[0]
yaml2.Unmarshal(inb, out) // $unmarshaler=yaml: inb -> definition of out $ttfnmodelstep=inb -> definition of out
yaml2.UnmarshalStrict(inb, out) // $unmarshaler=yaml: inb -> definition of out $ttfnmodelstep=inb -> definition of out
var r io.Reader
d := yaml2.NewDecoder(r) // $ttfnmodelstep=r -> call to NewDecoder
d.Decode(out) // $ttfnmodelstep=d -> definition of out
var w io.Writer
e := yaml2.NewEncoder(w) // $ttfnmodelstep=definition of e -> definition of w
e.Encode(in) // $ttfnmodelstep=in -> definition of e
out, _ = yaml3.Marshal(in) // $marshaler=yaml: in -> ... = ...[0] $ttfnmodelstep=in -> ... = ...[0]
yaml3.Unmarshal(inb, out) // $unmarshaler=yaml: inb -> definition of out $ttfnmodelstep=inb -> definition of out
d1 := yaml3.NewDecoder(r) // $ttfnmodelstep=r -> call to NewDecoder
d1.Decode(out) // $ttfnmodelstep=d1 -> definition of out
e1 := yaml3.NewEncoder(w) // $ttfnmodelstep=definition of e1 -> definition of w
e1.Encode(in) // $ttfnmodelstep=in -> definition of e1
var n1 yaml3.Node
n1.Decode(out) // $ttfnmodelstep=n1 -> definition of out
n1.Encode(in) // $ttfnmodelstep=in -> definition of n1
}