Lars 2021-11-24 16:34:42 +01:00 committed by GitHub
parent c95e9c21e7
commit 6a41fb9e61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 132 deletions

View file

@ -38,11 +38,10 @@ func contains(methods []string, method string) bool {
func (r *badDefer) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { func (r *badDefer) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
if deferStmt, ok := n.(*ast.DeferStmt); ok { if deferStmt, ok := n.(*ast.DeferStmt); ok {
for _, deferTyp := range r.types { for _, deferTyp := range r.types {
if issue := r.checkChild(n, c, deferStmt.Call, deferTyp); issue != nil { if typ, method, err := gosec.GetCallInfo(deferStmt.Call, c); err == nil {
return issue, nil if normalize(typ) == deferTyp.typ && contains(deferTyp.methods, method) {
} return gosec.NewIssue(c, n, r.ID(), fmt.Sprintf(r.What, method, typ), r.Severity, r.Confidence), nil
if issue := r.checkFunction(n, c, deferStmt, deferTyp); issue != nil { }
return issue, nil
} }
} }
} }
@ -50,42 +49,6 @@ func (r *badDefer) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
return nil, nil return nil, nil
} }
func (r *badDefer) checkChild(n ast.Node, c *gosec.Context, callExp *ast.CallExpr, deferTyp deferType) *gosec.Issue {
if typ, method, err := gosec.GetCallInfo(callExp, c); err == nil {
if normalize(typ) == deferTyp.typ && contains(deferTyp.methods, method) {
return gosec.NewIssue(c, n, r.ID(), fmt.Sprintf(r.What, method, typ), r.Severity, r.Confidence)
}
}
return nil
}
func (r *badDefer) checkFunction(n ast.Node, c *gosec.Context, deferStmt *ast.DeferStmt, deferTyp deferType) *gosec.Issue {
if anonFunc, isAnonFunc := deferStmt.Call.Fun.(*ast.FuncLit); isAnonFunc {
for _, subElem := range anonFunc.Body.List {
if issue := r.checkStmt(n, c, subElem, deferTyp); issue != nil {
return issue
}
}
}
return nil
}
func (r *badDefer) checkStmt(n ast.Node, c *gosec.Context, subElem ast.Stmt, deferTyp deferType) *gosec.Issue {
switch stmt := subElem.(type) {
case *ast.AssignStmt:
for _, rh := range stmt.Rhs {
if e, isCallExp := rh.(*ast.CallExpr); isCallExp {
return r.checkChild(n, c, e, deferTyp)
}
}
case *ast.IfStmt:
if s, is := stmt.Init.(*ast.AssignStmt); is {
return r.checkStmt(n, c, s, deferTyp)
}
}
return nil
}
// NewDeferredClosing detects unsafe defer of error returning methods // NewDeferredClosing detects unsafe defer of error returning methods
func NewDeferredClosing(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { func NewDeferredClosing(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
return &badDefer{ return &badDefer{

View file

@ -2192,120 +2192,37 @@ func main() {
// SampleCodeG307 - Unsafe defer of os.Close // SampleCodeG307 - Unsafe defer of os.Close
SampleCodeG307 = []CodeSample{ SampleCodeG307 = []CodeSample{
{[]string{`package main {[]string{`package main
import ( import (
"bufio"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
) )
func check(e error) { func check(e error) {
if e != nil { if e != nil {
panic(e) panic(e)
} }
} }
func main() { func main() {
d1 := []byte("hello\ngo\n") d1 := []byte("hello\ngo\n")
err := ioutil.WriteFile("/tmp/dat1", d1, 0744) err := ioutil.WriteFile("/tmp/dat1", d1, 0744)
check(err) check(err)
allowed := ioutil.WriteFile("/tmp/dat1", d1, 0600) allowed := ioutil.WriteFile("/tmp/dat1", d1, 0600)
check(allowed) check(allowed)
f, err := os.Create("/tmp/dat2") f, err := os.Create("/tmp/dat2")
check(err) check(err)
defer f.Close() defer f.Close()
d2 := []byte{115, 111, 109, 101, 10} d2 := []byte{115, 111, 109, 101, 10}
n2, err := f.Write(d2) n2, err := f.Write(d2)
defer check(err) defer check(err)
fmt.Printf("wrote %d bytes\n", n2) fmt.Printf("wrote %d bytes\n", n2)
n3, err := f.WriteString("writes\n")
}`}, 1, gosec.NewConfig()}, fmt.Printf("wrote %d bytes\n", n3)
{[]string{`package main f.Sync()
w := bufio.NewWriter(f)
import ( n4, err := w.WriteString("buffered\n")
"fmt" fmt.Printf("wrote %d bytes\n", n4)
"io/ioutil" w.Flush()
"log"
"os"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
d1 := []byte("hello\ngo\n")
err := ioutil.WriteFile("/tmp/dat1", d1, 0744)
check(err)
allowed := ioutil.WriteFile("/tmp/dat1", d1, 0600)
check(allowed)
f, err := os.Create("/tmp/dat2")
check(err)
defer func() {
if err := f.Close(); err != nil {
log.Println(err)
}
}()
d2 := []byte{115, 111, 109, 101, 10}
n2, err := f.Write(d2)
defer check(err)
fmt.Printf("wrote %d bytes\n", n2)
}`}, 1, gosec.NewConfig()},
{[]string{`package main
import (
"fmt"
"io/ioutil"
"log"
"os"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
d1 := []byte("hello\ngo\n")
err := ioutil.WriteFile("/tmp/dat1", d1, 0744)
check(err)
allowed := ioutil.WriteFile("/tmp/dat1", d1, 0600)
check(allowed)
f, err := os.Create("/tmp/dat2")
check(err)
defer func() {
err := f.Close()
if err != nil {
log.Println(err)
}
}()
d2 := []byte{115, 111, 109, 101, 10}
n2, err := f.Write(d2)
defer check(err)
fmt.Printf("wrote %d bytes\n", n2)
}`}, 1, gosec.NewConfig()}, }`}, 1, gosec.NewConfig()},
} }