mirror of
https://github.com/securego/gosec.git
synced 2024-12-25 20:15:54 +00:00
340 lines
11 KiB
Go
340 lines
11 KiB
Go
package gosec_test
|
|
|
|
import (
|
|
"go/ast"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/securego/gosec/v2"
|
|
"github.com/securego/gosec/v2/testutils"
|
|
)
|
|
|
|
var _ = Describe("Resolve ast node to concrete value", func() {
|
|
Context("when attempting to resolve an ast node", func() {
|
|
It("should successfully resolve basic literal", func() {
|
|
var basicLiteral *ast.BasicLit
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const foo = "bar"; func main(){}`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.BasicLit); ok {
|
|
basicLiteral = node
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(basicLiteral).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(basicLiteral, ctx)).Should(BeTrue())
|
|
})
|
|
|
|
It("should successfully resolve identifier", func() {
|
|
var ident *ast.Ident
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; var foo string = "bar"; func main(){}`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.Ident); ok {
|
|
ident = node
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(ident).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(ident, ctx)).Should(BeTrue())
|
|
})
|
|
|
|
It("should successfully resolve variable identifier", func() {
|
|
var ident *ast.Ident
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; import "fmt"; func main(){ x := "test"; y := x; fmt.Println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.Ident); ok && node.Name == "y" {
|
|
ident = node
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(ident).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(ident, ctx)).Should(BeTrue())
|
|
})
|
|
|
|
It("should successfully not resolve variable identifier with no declaration", func() {
|
|
var ident *ast.Ident
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; import "fmt"; func main(){ x := "test"; y := x; fmt.Println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.Ident); ok && node.Name == "y" {
|
|
ident = node
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(ident).ShouldNot(BeNil())
|
|
ident.Obj.Decl = nil
|
|
Expect(gosec.TryResolve(ident, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully resolve assign statement", func() {
|
|
var assign *ast.AssignStmt
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const x = "bar"; func main(){ y := x; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.AssignStmt); ok {
|
|
if id, ok := node.Lhs[0].(*ast.Ident); ok && id.Name == "y" {
|
|
assign = node
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(assign).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(assign, ctx)).Should(BeTrue())
|
|
})
|
|
|
|
It("should successfully not resolve assign statement without rhs", func() {
|
|
var assign *ast.AssignStmt
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const x = "bar"; func main(){ y := x; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.AssignStmt); ok {
|
|
if id, ok := node.Lhs[0].(*ast.Ident); ok && id.Name == "y" {
|
|
assign = node
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(assign).ShouldNot(BeNil())
|
|
assign.Rhs = []ast.Expr{}
|
|
Expect(gosec.TryResolve(assign, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully not resolve assign statement with unsolvable rhs", func() {
|
|
var assign *ast.AssignStmt
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const x = "bar"; func main(){ y := x; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.AssignStmt); ok {
|
|
if id, ok := node.Lhs[0].(*ast.Ident); ok && id.Name == "y" {
|
|
assign = node
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(assign).ShouldNot(BeNil())
|
|
assign.Rhs = []ast.Expr{&ast.CallExpr{}}
|
|
Expect(gosec.TryResolve(assign, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully resolve a binary statement", func() {
|
|
var target *ast.BinaryExpr
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const (x = "bar"; y = "baz"); func main(){ z := x + y; println(z) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.BinaryExpr); ok {
|
|
target = node
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(target).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(target, ctx)).Should(BeTrue())
|
|
})
|
|
|
|
It("should successfully resolve value spec", func() {
|
|
var value *ast.ValueSpec
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const x = "bar"; func main(){ var y string = x; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.ValueSpec); ok {
|
|
if len(node.Names) == 1 && node.Names[0].Name == "y" {
|
|
value = node
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeTrue())
|
|
})
|
|
It("should successfully not resolve value spec without values", func() {
|
|
var value *ast.ValueSpec
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const x = "bar"; func main(){ var y string = x; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.ValueSpec); ok {
|
|
if len(node.Names) == 1 && node.Names[0].Name == "y" {
|
|
value = node
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
value.Values = []ast.Expr{}
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully not resolve value spec with unsolvable value", func() {
|
|
var value *ast.ValueSpec
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; const x = "bar"; func main(){ var y string = x; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.ValueSpec); ok {
|
|
if len(node.Names) == 1 && node.Names[0].Name == "y" {
|
|
value = node
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
value.Values = []ast.Expr{&ast.CallExpr{}}
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully resolve composite literal", func() {
|
|
var value *ast.CompositeLit
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; func main(){ y := []string{"value1", "value2"}; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.CompositeLit); ok {
|
|
value = node
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeTrue())
|
|
})
|
|
|
|
It("should successfully not resolve composite literal without elst", func() {
|
|
var value *ast.CompositeLit
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; func main(){ y := []string{"value1", "value2"}; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.CompositeLit); ok {
|
|
value = node
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
value.Elts = []ast.Expr{}
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully not resolve composite literal with unsolvable elst", func() {
|
|
var value *ast.CompositeLit
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; func main(){ y := []string{"value1", "value2"}; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.CompositeLit); ok {
|
|
value = node
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
value.Elts = []ast.Expr{&ast.CallExpr{}}
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully not resolve call expressions", func() {
|
|
var value *ast.CallExpr
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; func main(){ y := []string{"value1", "value2"}; println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.CallExpr); ok {
|
|
value = node
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeFalse())
|
|
})
|
|
|
|
It("should successfully not resolve call expressions", func() {
|
|
var value *ast.ImportSpec
|
|
pkg := testutils.NewTestPackage()
|
|
defer pkg.Close()
|
|
pkg.AddFile("foo.go", `package main; import "fmt"; func main(){ y := []string{"value1", "value2"}; fmt.Println(y) }`)
|
|
ctx := pkg.CreateContext("foo.go")
|
|
v := testutils.NewMockVisitor()
|
|
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
|
if node, ok := n.(*ast.ImportSpec); ok {
|
|
value = node
|
|
}
|
|
return true
|
|
}
|
|
v.Context = ctx
|
|
ast.Walk(v, ctx.Root)
|
|
Expect(value).ShouldNot(BeNil())
|
|
Expect(gosec.TryResolve(value, ctx)).Should(BeFalse())
|
|
})
|
|
})
|
|
})
|