50 lines
1.6 KiB
Go
50 lines
1.6 KiB
Go
package sa1021
|
|
|
|
import (
|
|
"go/types"
|
|
|
|
"honnef.co/go/tools/analysis/callcheck"
|
|
"honnef.co/go/tools/analysis/lint"
|
|
"honnef.co/go/tools/go/ir"
|
|
"honnef.co/go/tools/internal/passes/buildir"
|
|
"honnef.co/go/tools/knowledge"
|
|
|
|
"golang.org/x/tools/go/analysis"
|
|
)
|
|
|
|
var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
|
|
Analyzer: &analysis.Analyzer{
|
|
Name: "SA1021",
|
|
Requires: []*analysis.Analyzer{buildir.Analyzer},
|
|
Run: callcheck.Analyzer(rules),
|
|
},
|
|
Doc: &lint.RawDocumentation{
|
|
Title: `Using \'bytes.Equal\' to compare two \'net.IP\'`,
|
|
Text: `A \'net.IP\' stores an IPv4 or IPv6 address as a slice of bytes. The
|
|
length of the slice for an IPv4 address, however, can be either 4 or
|
|
16 bytes long, using different ways of representing IPv4 addresses. In
|
|
order to correctly compare two \'net.IP\'s, the \'net.IP.Equal\' method should
|
|
be used, as it takes both representations into account.`,
|
|
Since: "2017.1",
|
|
Severity: lint.SeverityWarning,
|
|
MergeIf: lint.MergeIfAny,
|
|
},
|
|
})
|
|
|
|
var Analyzer = SCAnalyzer.Analyzer
|
|
|
|
var rules = map[string]callcheck.Check{
|
|
"bytes.Equal": func(call *callcheck.Call) {
|
|
if isConvertedFrom(call.Args[knowledge.Arg("bytes.Equal.a")].Value, "net.IP") &&
|
|
isConvertedFrom(call.Args[knowledge.Arg("bytes.Equal.b")].Value, "net.IP") {
|
|
call.Invalid("use net.IP.Equal to compare net.IPs, not bytes.Equal")
|
|
}
|
|
},
|
|
}
|
|
|
|
// ConvertedFrom reports whether value v was converted from type typ.
|
|
func isConvertedFrom(v callcheck.Value, typ string) bool {
|
|
change, ok := v.Value.(*ir.ChangeType)
|
|
return ok && types.TypeString(types.Unalias(change.X.Type()), nil) == typ
|
|
}
|