Files
2026-06-06 01:17:29 +00:00

53 lines
1.5 KiB
Go

package sa1014
import (
"fmt"
"go/types"
"honnef.co/go/tools/analysis/callcheck"
"honnef.co/go/tools/analysis/lint"
"honnef.co/go/tools/internal/passes/buildir"
"golang.org/x/tools/go/analysis"
)
var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
Analyzer: &analysis.Analyzer{
Name: "SA1014",
Requires: []*analysis.Analyzer{buildir.Analyzer},
Run: callcheck.Analyzer(checkUnmarshalPointerRules),
},
Doc: &lint.RawDocumentation{
Title: `Non-pointer value passed to \'Unmarshal\' or \'Decode\'`,
Since: "2017.1",
Severity: lint.SeverityError,
MergeIf: lint.MergeIfAny,
},
})
var Analyzer = SCAnalyzer.Analyzer
var checkUnmarshalPointerRules = map[string]callcheck.Check{
"encoding/xml.Unmarshal": unmarshalPointer("xml.Unmarshal", 1),
"(*encoding/xml.Decoder).Decode": unmarshalPointer("Decode", 0),
"(*encoding/xml.Decoder).DecodeElement": unmarshalPointer("DecodeElement", 0),
"encoding/json.Unmarshal": unmarshalPointer("json.Unmarshal", 1),
"(*encoding/json.Decoder).Decode": unmarshalPointer("Decode", 0),
}
func unmarshalPointer(name string, arg int) callcheck.Check {
return func(call *callcheck.Call) {
if !Pointer(call.Args[arg].Value) {
call.Args[arg].Invalid(fmt.Sprintf("%s expects to unmarshal into a pointer, but the provided value is not a pointer", name))
}
}
}
func Pointer(v callcheck.Value) bool {
switch v.Value.Type().Underlying().(type) {
case *types.Pointer, *types.Interface:
return true
}
return false
}