2018-07-19 17:42:25 +01:00
|
|
|
package gosec_test
|
2016-11-18 17:57:34 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"go/ast"
|
2017-07-19 22:17:00 +01:00
|
|
|
|
2022-01-03 17:11:35 +00:00
|
|
|
. "github.com/onsi/ginkgo/v2"
|
2017-07-19 22:17:00 +01:00
|
|
|
. "github.com/onsi/gomega"
|
2023-03-30 08:31:24 +01:00
|
|
|
|
2020-04-01 21:18:39 +01:00
|
|
|
"github.com/securego/gosec/v2"
|
|
|
|
"github.com/securego/gosec/v2/testutils"
|
2016-11-18 17:57:34 +00:00
|
|
|
)
|
|
|
|
|
2019-04-29 17:32:39 +01:00
|
|
|
var _ = Describe("Call List", func() {
|
2021-05-31 09:44:12 +01:00
|
|
|
var calls gosec.CallList
|
2017-07-19 22:17:00 +01:00
|
|
|
BeforeEach(func() {
|
2018-07-19 17:42:25 +01:00
|
|
|
calls = gosec.NewCallList()
|
2017-07-19 22:17:00 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
It("should not return any matches when empty", func() {
|
|
|
|
Expect(calls.Contains("foo", "bar")).Should(BeFalse())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("should be possible to add a single call", func() {
|
2023-04-04 07:52:59 +01:00
|
|
|
Expect(calls).Should(BeEmpty())
|
2017-07-19 22:17:00 +01:00
|
|
|
calls.Add("foo", "bar")
|
|
|
|
Expect(calls).Should(HaveLen(1))
|
|
|
|
|
|
|
|
expected := make(map[string]bool)
|
|
|
|
expected["bar"] = true
|
|
|
|
actual := map[string]bool(calls["foo"])
|
|
|
|
Expect(actual).Should(Equal(expected))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("should be possible to add multiple calls at once", func() {
|
2023-04-04 07:52:59 +01:00
|
|
|
Expect(calls).Should(BeEmpty())
|
2017-07-19 22:17:00 +01:00
|
|
|
calls.AddAll("fmt", "Sprint", "Sprintf", "Printf", "Println")
|
|
|
|
|
|
|
|
expected := map[string]bool{
|
|
|
|
"Sprint": true,
|
|
|
|
"Sprintf": true,
|
|
|
|
"Printf": true,
|
|
|
|
"Println": true,
|
|
|
|
}
|
|
|
|
actual := map[string]bool(calls["fmt"])
|
|
|
|
Expect(actual).Should(Equal(expected))
|
|
|
|
})
|
|
|
|
|
2020-01-28 13:11:00 +00:00
|
|
|
It("should be possible to add pointer call", func() {
|
2023-04-04 07:52:59 +01:00
|
|
|
Expect(calls).Should(BeEmpty())
|
2020-01-28 13:11:00 +00:00
|
|
|
calls.Add("*bytes.Buffer", "WriteString")
|
|
|
|
actual := calls.ContainsPointer("*bytes.Buffer", "WriteString")
|
|
|
|
Expect(actual).Should(BeTrue())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("should be possible to check pointer call", func() {
|
2023-04-04 07:52:59 +01:00
|
|
|
Expect(calls).Should(BeEmpty())
|
2020-01-28 13:11:00 +00:00
|
|
|
calls.Add("bytes.Buffer", "WriteString")
|
|
|
|
actual := calls.ContainsPointer("*bytes.Buffer", "WriteString")
|
|
|
|
Expect(actual).Should(BeTrue())
|
|
|
|
})
|
|
|
|
|
2017-07-19 22:17:00 +01:00
|
|
|
It("should not return a match if none are present", func() {
|
|
|
|
calls.Add("ioutil", "Copy")
|
|
|
|
Expect(calls.Contains("fmt", "Println")).Should(BeFalse())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("should match a call based on selector and ident", func() {
|
|
|
|
calls.Add("ioutil", "Copy")
|
|
|
|
Expect(calls.Contains("ioutil", "Copy")).Should(BeTrue())
|
|
|
|
})
|
|
|
|
|
2020-01-28 13:11:00 +00:00
|
|
|
It("should match a package call expression", func() {
|
2017-07-19 22:17:00 +01:00
|
|
|
// Create file to be scanned
|
|
|
|
pkg := testutils.NewTestPackage()
|
|
|
|
defer pkg.Close()
|
2018-09-28 09:42:25 +01:00
|
|
|
pkg.AddFile("md5.go", testutils.SampleCodeG401[0].Code[0])
|
2017-07-19 22:17:00 +01:00
|
|
|
|
|
|
|
ctx := pkg.CreateContext("md5.go")
|
|
|
|
|
|
|
|
// Search for md5.New()
|
2018-01-05 13:05:53 +00:00
|
|
|
calls.Add("crypto/md5", "New")
|
2017-07-19 22:17:00 +01:00
|
|
|
|
|
|
|
// Stub out visitor and count number of matched call expr
|
|
|
|
matched := 0
|
|
|
|
v := testutils.NewMockVisitor()
|
|
|
|
v.Context = ctx
|
2018-07-19 17:42:25 +01:00
|
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
2020-01-28 13:11:00 +00:00
|
|
|
if _, ok := n.(*ast.CallExpr); ok && calls.ContainsPkgCallExpr(n, ctx, false) != nil {
|
2017-07-19 22:17:00 +01:00
|
|
|
matched++
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
ast.Walk(v, ctx.Root)
|
|
|
|
Expect(matched).Should(Equal(1))
|
|
|
|
})
|
|
|
|
|
2024-06-20 12:02:59 +01:00
|
|
|
It("should match a package call expression", func() {
|
|
|
|
// Create file to be scanned
|
|
|
|
pkg := testutils.NewTestPackage()
|
|
|
|
defer pkg.Close()
|
|
|
|
pkg.AddFile("cipher.go", testutils.SampleCodeG405[0].Code[0])
|
|
|
|
|
|
|
|
ctx := pkg.CreateContext("cipher.go")
|
|
|
|
|
|
|
|
// Search for des.NewCipher()
|
|
|
|
calls.Add("crypto/des", "NewCipher")
|
|
|
|
|
|
|
|
// Stub out visitor and count number of matched call expr
|
|
|
|
matched := 0
|
|
|
|
v := testutils.NewMockVisitor()
|
|
|
|
v.Context = ctx
|
2024-06-24 18:16:32 +01:00
|
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
|
|
if _, ok := n.(*ast.CallExpr); ok && calls.ContainsPkgCallExpr(n, ctx, false) != nil {
|
|
|
|
matched++
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
ast.Walk(v, ctx.Root)
|
|
|
|
Expect(matched).Should(Equal(1))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("should match a package call expression", func() {
|
|
|
|
// Create file to be scanned
|
|
|
|
pkg := testutils.NewTestPackage()
|
|
|
|
defer pkg.Close()
|
|
|
|
pkg.AddFile("md4.go", testutils.SampleCodeG406[0].Code[0])
|
|
|
|
|
|
|
|
ctx := pkg.CreateContext("md4.go")
|
|
|
|
|
|
|
|
// Search for md4.New()
|
|
|
|
calls.Add("golang.org/x/crypto/md4", "New")
|
|
|
|
|
|
|
|
// Stub out visitor and count number of matched call expr
|
|
|
|
matched := 0
|
|
|
|
v := testutils.NewMockVisitor()
|
|
|
|
v.Context = ctx
|
2024-06-20 12:02:59 +01:00
|
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
|
|
if _, ok := n.(*ast.CallExpr); ok && calls.ContainsPkgCallExpr(n, ctx, false) != nil {
|
|
|
|
matched++
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
ast.Walk(v, ctx.Root)
|
|
|
|
Expect(matched).Should(Equal(1))
|
|
|
|
})
|
|
|
|
|
2020-01-28 13:11:00 +00:00
|
|
|
It("should match a call expression", func() {
|
|
|
|
// Create file to be scanned
|
|
|
|
pkg := testutils.NewTestPackage()
|
|
|
|
defer pkg.Close()
|
2020-03-15 14:42:26 +00:00
|
|
|
pkg.AddFile("main.go", testutils.SampleCodeG104[6].Code[0])
|
2020-01-28 13:11:00 +00:00
|
|
|
|
|
|
|
ctx := pkg.CreateContext("main.go")
|
|
|
|
|
|
|
|
calls.Add("bytes.Buffer", "WriteString")
|
|
|
|
calls.Add("strings.Builder", "WriteString")
|
|
|
|
calls.Add("io.Pipe", "CloseWithError")
|
|
|
|
calls.Add("fmt", "Fprintln")
|
|
|
|
|
|
|
|
// Stub out visitor and count number of matched call expr
|
|
|
|
matched := 0
|
|
|
|
v := testutils.NewMockVisitor()
|
|
|
|
v.Context = ctx
|
|
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
|
|
if _, ok := n.(*ast.CallExpr); ok && calls.ContainsCallExpr(n, ctx) != nil {
|
|
|
|
matched++
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
ast.Walk(v, ctx.Root)
|
|
|
|
Expect(matched).Should(Equal(5))
|
|
|
|
})
|
2017-07-19 22:17:00 +01:00
|
|
|
})
|