Add errchkjson linter (#2362)
This commit is contained in:
parent
fc888cf0cb
commit
55358972d6
@ -137,6 +137,24 @@ linters-settings:
|
|||||||
- io.Copy(*bytes.Buffer)
|
- io.Copy(*bytes.Buffer)
|
||||||
- io.Copy(os.Stdout)
|
- io.Copy(os.Stdout)
|
||||||
|
|
||||||
|
errchkjson:
|
||||||
|
# with check-error-free-encoding set to true, errchkjson does warn about errors
|
||||||
|
# from json encoding functions that are safe to be ignored,
|
||||||
|
# because they are not possible to happen (default false)
|
||||||
|
#
|
||||||
|
# if check-error-free-encoding is set to true and errcheck linter is enabled,
|
||||||
|
# it is recommended to add the following exceptions to prevent from false positives:
|
||||||
|
#
|
||||||
|
# linters-settings:
|
||||||
|
# errcheck:
|
||||||
|
# exclude-functions:
|
||||||
|
# - encoding/json.Marshal
|
||||||
|
# - encoding/json.MarshalIndent
|
||||||
|
# - (*encoding/json.Encoder).Encode
|
||||||
|
check-error-free-encoding: false
|
||||||
|
# if report-no-exported is true, encoding a struct without exported fields is reported as issue (default false)
|
||||||
|
report-no-exported: false
|
||||||
|
|
||||||
errorlint:
|
errorlint:
|
||||||
# Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats
|
# Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats
|
||||||
errorf: true
|
errorf: true
|
||||||
|
1
go.mod
1
go.mod
@ -16,6 +16,7 @@ require (
|
|||||||
github.com/blizzy78/varnamelen v0.5.0
|
github.com/blizzy78/varnamelen v0.5.0
|
||||||
github.com/bombsimon/wsl/v3 v3.3.0
|
github.com/bombsimon/wsl/v3 v3.3.0
|
||||||
github.com/breml/bidichk v0.2.1
|
github.com/breml/bidichk v0.2.1
|
||||||
|
github.com/breml/errchkjson v0.2.0
|
||||||
github.com/butuzov/ireturn v0.1.1
|
github.com/butuzov/ireturn v0.1.1
|
||||||
github.com/charithe/durationcheck v0.0.9
|
github.com/charithe/durationcheck v0.0.9
|
||||||
github.com/daixiang0/gci v0.2.9
|
github.com/daixiang0/gci v0.2.9
|
||||||
|
2
go.sum
generated
2
go.sum
generated
@ -108,6 +108,8 @@ github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxj
|
|||||||
github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
||||||
github.com/breml/bidichk v0.2.1 h1:SRNtZuLdfkxtocj+xyHXKC1Uv3jVi6EPYx+NHSTNQvE=
|
github.com/breml/bidichk v0.2.1 h1:SRNtZuLdfkxtocj+xyHXKC1Uv3jVi6EPYx+NHSTNQvE=
|
||||||
github.com/breml/bidichk v0.2.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso=
|
github.com/breml/bidichk v0.2.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso=
|
||||||
|
github.com/breml/errchkjson v0.2.0 h1:5XK9tXXqahYiPHuJ5Asx9a5ucpASxLMxq3EvQyLb26c=
|
||||||
|
github.com/breml/errchkjson v0.2.0/go.mod h1:jZEATw/jF69cL1iy7//Yih8yp/mXp2CBoBr9GJwCAsY=
|
||||||
github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY=
|
github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY=
|
||||||
github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc=
|
github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
@ -89,6 +89,7 @@ type LintersSettings struct {
|
|||||||
Dogsled DogsledSettings
|
Dogsled DogsledSettings
|
||||||
Dupl DuplSettings
|
Dupl DuplSettings
|
||||||
Errcheck ErrcheckSettings
|
Errcheck ErrcheckSettings
|
||||||
|
ErrChkJSON ErrChkJSONSettings
|
||||||
ErrorLint ErrorLintSettings
|
ErrorLint ErrorLintSettings
|
||||||
Exhaustive ExhaustiveSettings
|
Exhaustive ExhaustiveSettings
|
||||||
ExhaustiveStruct ExhaustiveStructSettings
|
ExhaustiveStruct ExhaustiveStructSettings
|
||||||
@ -165,6 +166,11 @@ type Cyclop struct {
|
|||||||
SkipTests bool `mapstructure:"skip-tests"`
|
SkipTests bool `mapstructure:"skip-tests"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ErrChkJSONSettings struct {
|
||||||
|
CheckErrorFreeEncoding bool `mapstructure:"check-error-free-encoding"`
|
||||||
|
ReportNoExported bool `mapstructure:"report-no-exported"`
|
||||||
|
}
|
||||||
|
|
||||||
type DepGuardSettings struct {
|
type DepGuardSettings struct {
|
||||||
ListType string `mapstructure:"list-type"`
|
ListType string `mapstructure:"list-type"`
|
||||||
Packages []string
|
Packages []string
|
||||||
|
33
pkg/golinters/errchkjson.go
Normal file
33
pkg/golinters/errchkjson.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package golinters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/breml/errchkjson"
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
|
||||||
|
"github.com/golangci/golangci-lint/pkg/config"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewErrChkJSONFuncName(cfg *config.ErrChkJSONSettings) *goanalysis.Linter {
|
||||||
|
a := errchkjson.NewAnalyzer()
|
||||||
|
|
||||||
|
cfgMap := map[string]map[string]interface{}{}
|
||||||
|
cfgMap[a.Name] = map[string]interface{}{
|
||||||
|
"omit-safe": true,
|
||||||
|
}
|
||||||
|
if cfg != nil {
|
||||||
|
cfgMap[a.Name] = map[string]interface{}{
|
||||||
|
"omit-safe": !cfg.CheckErrorFreeEncoding,
|
||||||
|
"report-no-exported": cfg.ReportNoExported,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return goanalysis.NewLinter(
|
||||||
|
"errchkjson",
|
||||||
|
"Checks types passed to the json encoding functions. "+
|
||||||
|
"Reports unsupported types and optionally reports occations, "+
|
||||||
|
"where the check for the returned error can be omitted.",
|
||||||
|
[]*analysis.Analyzer{a},
|
||||||
|
cfgMap,
|
||||||
|
).WithLoadMode(goanalysis.LoadModeTypesInfo)
|
||||||
|
}
|
@ -102,6 +102,7 @@ func enableLinterConfigs(lcs []*linter.Config, isEnabled func(lc *linter.Config)
|
|||||||
func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
||||||
var bidichkCfg *config.BiDiChkSettings
|
var bidichkCfg *config.BiDiChkSettings
|
||||||
var cyclopCfg *config.Cyclop
|
var cyclopCfg *config.Cyclop
|
||||||
|
var errchkjsonCfg *config.ErrChkJSONSettings
|
||||||
var errorlintCfg *config.ErrorLintSettings
|
var errorlintCfg *config.ErrorLintSettings
|
||||||
var exhaustiveCfg *config.ExhaustiveSettings
|
var exhaustiveCfg *config.ExhaustiveSettings
|
||||||
var exhaustiveStructCfg *config.ExhaustiveStructSettings
|
var exhaustiveStructCfg *config.ExhaustiveStructSettings
|
||||||
@ -129,6 +130,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
|||||||
if m.cfg != nil {
|
if m.cfg != nil {
|
||||||
bidichkCfg = &m.cfg.LintersSettings.BiDiChk
|
bidichkCfg = &m.cfg.LintersSettings.BiDiChk
|
||||||
cyclopCfg = &m.cfg.LintersSettings.Cyclop
|
cyclopCfg = &m.cfg.LintersSettings.Cyclop
|
||||||
|
errchkjsonCfg = &m.cfg.LintersSettings.ErrChkJSON
|
||||||
errorlintCfg = &m.cfg.LintersSettings.ErrorLint
|
errorlintCfg = &m.cfg.LintersSettings.ErrorLint
|
||||||
exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive
|
exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive
|
||||||
exhaustiveStructCfg = &m.cfg.LintersSettings.ExhaustiveStruct
|
exhaustiveStructCfg = &m.cfg.LintersSettings.ExhaustiveStruct
|
||||||
@ -548,6 +550,11 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
|||||||
WithSince("1.43.0").
|
WithSince("1.43.0").
|
||||||
WithPresets(linter.PresetBugs).
|
WithPresets(linter.PresetBugs).
|
||||||
WithURL("https://github.com/breml/bidichk"),
|
WithURL("https://github.com/breml/bidichk"),
|
||||||
|
linter.NewConfig(golinters.NewErrChkJSONFuncName(errchkjsonCfg)).
|
||||||
|
WithSince("1.44.0").
|
||||||
|
WithPresets(linter.PresetBugs).
|
||||||
|
WithLoadForGoAnalysis().
|
||||||
|
WithURL("https://github.com/breml/errchkjson"),
|
||||||
|
|
||||||
// nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives
|
// nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives
|
||||||
linter.NewConfig(golinters.NewNoLintLint()).
|
linter.NewConfig(golinters.NewNoLintLint()).
|
||||||
|
2
test/testdata/configs/errchkjson.yml
vendored
Normal file
2
test/testdata/configs/errchkjson.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
issues:
|
||||||
|
max-issues-per-linter: 100
|
5
test/testdata/configs/errchkjson_check_error_free_encoding.yml
vendored
Normal file
5
test/testdata/configs/errchkjson_check_error_free_encoding.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
issues:
|
||||||
|
max-issues-per-linter: 100
|
||||||
|
linters-settings:
|
||||||
|
errchkjson:
|
||||||
|
check-error-free-encoding: true
|
3
test/testdata/configs/errchkjson_no_exported.yml
vendored
Normal file
3
test/testdata/configs/errchkjson_no_exported.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
linters-settings:
|
||||||
|
errchkjson:
|
||||||
|
report-no-exported: true
|
641
test/testdata/errchkjson.go
vendored
Normal file
641
test/testdata/errchkjson.go
vendored
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
// args: -Eerrchkjson
|
||||||
|
// config_path: testdata/configs/errchkjson.yml
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type marshalText struct{}
|
||||||
|
|
||||||
|
func (mt marshalText) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(`mt`), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ encoding.TextMarshaler = marshalText(struct{}{})
|
||||||
|
|
||||||
|
// JSONMarshalSafeTypesWithNoSafe contains a multitude of test cases to marshal different combinations of types to JSON,
|
||||||
|
// that are safe, that is, they will never return an error, if these types are marshaled to JSON.
|
||||||
|
func JSONMarshalSafeTypesWithNoSafe() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
_, _ = json.Marshal(nil) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
json.Marshal(nil) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(nil) // nil is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
_, _ = json.MarshalIndent(nil, "", " ") // ERROR "Error return value of `encoding/json.MarshalIndent` is not checked"
|
||||||
|
json.MarshalIndent(nil, "", " ") // ERROR "Error return value of `encoding/json.MarshalIndent` is not checked"
|
||||||
|
_, err = json.MarshalIndent(nil, "", " ") // nil is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
enc := json.NewEncoder(ioutil.Discard)
|
||||||
|
_ = enc.Encode(nil) // ERROR "Error return value of `\\([*]encoding/json.Encoder\\).Encode` is not checked"
|
||||||
|
enc.Encode(nil) // ERROR "Error return value of `\\([*]encoding/json.Encoder\\).Encode` is not checked"
|
||||||
|
err = enc.Encode(nil) // nil is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var b bool
|
||||||
|
_, _ = json.Marshal(b) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(b) // bool is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i int
|
||||||
|
_, _ = json.Marshal(i) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(i) // int is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i8 int8
|
||||||
|
_, _ = json.Marshal(i8) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(i8) // int8 is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i16 int16
|
||||||
|
_, _ = json.Marshal(i16) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(i16) // int16 is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i32 int32
|
||||||
|
_, _ = json.Marshal(i32) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(i32) // int32 / rune is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i64 int64
|
||||||
|
_, _ = json.Marshal(i64) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(i64) // int64 is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui uint
|
||||||
|
_, _ = json.Marshal(ui) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(ui) // uint is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui8 uint8
|
||||||
|
_, _ = json.Marshal(ui8) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(ui8) // uint8 is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui16 uint16
|
||||||
|
_, _ = json.Marshal(ui16) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(ui16) // uint16 is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui32 uint32
|
||||||
|
_, _ = json.Marshal(ui32) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(ui32) // uint32 is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui64 uint64
|
||||||
|
_, _ = json.Marshal(ui64) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(ui64) // uint64 is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var uiptr uintptr
|
||||||
|
_, _ = json.Marshal(uiptr) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(uiptr) // uintptr is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var str string
|
||||||
|
_, _ = json.Marshal(str) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(str) // string is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var strSlice []string
|
||||||
|
_, _ = json.Marshal(strSlice) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(strSlice) // []string is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var intSlice []int
|
||||||
|
_, _ = json.Marshal(intSlice) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(intSlice) // []int is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var boolSlice []bool
|
||||||
|
_, _ = json.Marshal(boolSlice) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(boolSlice) // []bool is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var strArray [10]string
|
||||||
|
_, _ = json.Marshal(strArray) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(strArray) // [10]string is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var intArray [10]int
|
||||||
|
_, _ = json.Marshal(intArray) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(intArray) // [10]int is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var boolArray [10]bool
|
||||||
|
_, _ = json.Marshal(boolArray) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(boolArray) // [10]bool is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var basicStruct struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
Int8 int8
|
||||||
|
Int16 int16
|
||||||
|
Int32 int32 // also rune
|
||||||
|
Int64 int64
|
||||||
|
Uint uint
|
||||||
|
Uint8 uint8 // also byte
|
||||||
|
Uint16 uint16
|
||||||
|
Uint32 uint32
|
||||||
|
Uint64 uint64
|
||||||
|
Uintptr uintptr
|
||||||
|
String string
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(basicStruct) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(basicStruct) // struct containing only safe basic types is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ptrStruct struct {
|
||||||
|
Bool *bool
|
||||||
|
Int *int
|
||||||
|
Int8 *int8
|
||||||
|
Int16 *int16
|
||||||
|
Int32 *int32
|
||||||
|
Int64 *int64
|
||||||
|
Uint *uint
|
||||||
|
Uint8 *uint8
|
||||||
|
Uint16 *uint16
|
||||||
|
Uint32 *uint32
|
||||||
|
Uint64 *uint64
|
||||||
|
Uintptr *uintptr
|
||||||
|
String *string
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(ptrStruct) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(ptrStruct) // struct containing pointer to only safe basic types is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrStr map[string]string
|
||||||
|
_, _ = json.Marshal(mapStrStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(mapStrStr) // map[string]string is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrInt map[string]int
|
||||||
|
_, _ = json.Marshal(mapStrInt) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(mapStrInt) // map[string]int is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrBool map[string]bool
|
||||||
|
_, _ = json.Marshal(mapStrBool) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(mapStrBool) // map[string]bool is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapIntStr map[int]string
|
||||||
|
_, _ = json.Marshal(mapIntStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(mapIntStr) // map[int]string is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapIntInt map[int]int
|
||||||
|
_, _ = json.Marshal(mapIntInt) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(mapIntInt) // map[int]int is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapIntBool map[int]bool
|
||||||
|
_, _ = json.Marshal(mapIntBool) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(mapIntBool) // map[int]bool is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
type innerStruct struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
String string
|
||||||
|
|
||||||
|
StrSlice []string
|
||||||
|
IntSlice []int
|
||||||
|
BoolSlice []bool
|
||||||
|
|
||||||
|
StrArray [10]string
|
||||||
|
IntArray [10]int
|
||||||
|
BoolArray [10]bool
|
||||||
|
|
||||||
|
MapStrStr map[string]string
|
||||||
|
MapStrInt map[string]int
|
||||||
|
MapStrBool map[string]bool
|
||||||
|
|
||||||
|
MapIntStr map[int]string
|
||||||
|
MapIntInt map[int]int
|
||||||
|
MapIntBool map[int]bool
|
||||||
|
}
|
||||||
|
var outerStruct struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
String string
|
||||||
|
|
||||||
|
StrSlice []string
|
||||||
|
IntSlice []int
|
||||||
|
BoolSlice []bool
|
||||||
|
|
||||||
|
StrArray [10]string
|
||||||
|
IntArray [10]int
|
||||||
|
BoolArray [10]bool
|
||||||
|
|
||||||
|
MapStrStr map[string]string
|
||||||
|
MapStrInt map[string]int
|
||||||
|
MapStrBool map[string]bool
|
||||||
|
|
||||||
|
MapIntStr map[int]string
|
||||||
|
MapIntInt map[int]int
|
||||||
|
MapIntBool map[int]bool
|
||||||
|
|
||||||
|
InnerStruct innerStruct
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(outerStruct) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(outerStruct) // struct with only safe types is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
structKey struct{ id int }
|
||||||
|
ExportedUnsafeAndInvalidStruct struct { // unsafe unexported but omitted
|
||||||
|
F64 float64
|
||||||
|
F64Ptr *float64
|
||||||
|
F64Slice []float64
|
||||||
|
F64Array [10]float64
|
||||||
|
MapStrF64 map[string]float64
|
||||||
|
MapEIStr map[interface{}]string
|
||||||
|
Number json.Number
|
||||||
|
NumberPtr *json.Number
|
||||||
|
NumberSlice []json.Number
|
||||||
|
MapNumberStr map[json.Number]string
|
||||||
|
Ei interface{}
|
||||||
|
Stringer fmt.Stringer
|
||||||
|
Mt marshalText
|
||||||
|
MapMarshalTextString map[marshalText]string
|
||||||
|
|
||||||
|
C128 complex128
|
||||||
|
C128Ptr *complex128
|
||||||
|
C128Slice []complex128
|
||||||
|
C128Array [10]complex128
|
||||||
|
MapBoolStr map[bool]string
|
||||||
|
MapF64Str map[float64]string
|
||||||
|
F func()
|
||||||
|
Ch chan struct{}
|
||||||
|
UnsafePtr unsafe.Pointer
|
||||||
|
MapStructStr map[structKey]string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// JSONMarshalSafeStructWithUnexportedFieldsWithNoSafe contains a struct with unexported, unsafe fields.
|
||||||
|
func JSONMarshalSaveStructWithUnexportedFieldsWithNoSafe() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var unexportedInStruct struct {
|
||||||
|
Bool bool // safe exported
|
||||||
|
|
||||||
|
f64 float64 // unsafe unexported
|
||||||
|
f64Ptr *float64 // unsafe unexported
|
||||||
|
f64Slice []float64 // unsafe unexported
|
||||||
|
f64Array [10]float64 // unsafe unexported
|
||||||
|
mapStrF64 map[string]float64 // unsafe unexported
|
||||||
|
mapEIStr map[interface{}]string // unsafe unexported
|
||||||
|
number json.Number // unsafe unexported
|
||||||
|
numberPtr *json.Number // unsafe unexported
|
||||||
|
numberSlice []json.Number // unsafe unexported
|
||||||
|
mapNumberStr map[json.Number]string // unsafe unexported
|
||||||
|
ei interface{} // unsafe unexported
|
||||||
|
stringer fmt.Stringer // unsafe unexported
|
||||||
|
mt marshalText // unsafe unexported
|
||||||
|
mapMarshalTextString map[marshalText]string // unsafe unexported
|
||||||
|
unexportedStruct ExportedUnsafeAndInvalidStruct // unsafe unexported
|
||||||
|
unexportedStructPtr *ExportedUnsafeAndInvalidStruct // unsafe unexported
|
||||||
|
|
||||||
|
c128 complex128 // invalid unexported
|
||||||
|
c128Slice []complex128 // invalid unexported
|
||||||
|
c128Array [10]complex128 // invalid unexported
|
||||||
|
mapBoolStr map[bool]string // invalid unexported
|
||||||
|
mapF64Str map[float64]string // invalid unexported
|
||||||
|
f func() // invalid unexported
|
||||||
|
ch chan struct{} // invalid unexported
|
||||||
|
unsafePtr unsafe.Pointer // invalid unexported
|
||||||
|
mapStructStr map[structKey]string // invalid unexported
|
||||||
|
}
|
||||||
|
_ = unexportedInStruct.f64
|
||||||
|
_ = unexportedInStruct.f64Ptr
|
||||||
|
_ = unexportedInStruct.f64Slice
|
||||||
|
_ = unexportedInStruct.f64Array
|
||||||
|
_ = unexportedInStruct.mapStrF64
|
||||||
|
_ = unexportedInStruct.mapEIStr
|
||||||
|
_ = unexportedInStruct.number
|
||||||
|
_ = unexportedInStruct.numberPtr
|
||||||
|
_ = unexportedInStruct.numberSlice
|
||||||
|
_ = unexportedInStruct.mapNumberStr
|
||||||
|
_ = unexportedInStruct.ei
|
||||||
|
_ = unexportedInStruct.stringer
|
||||||
|
_ = unexportedInStruct.mt
|
||||||
|
_ = unexportedInStruct.mapMarshalTextString
|
||||||
|
_ = unexportedInStruct.unexportedStruct
|
||||||
|
_ = unexportedInStruct.unexportedStructPtr
|
||||||
|
|
||||||
|
_ = unexportedInStruct.c128
|
||||||
|
_ = unexportedInStruct.c128Slice
|
||||||
|
_ = unexportedInStruct.c128Array
|
||||||
|
_ = unexportedInStruct.mapBoolStr
|
||||||
|
_ = unexportedInStruct.mapF64Str
|
||||||
|
_ = unexportedInStruct.f
|
||||||
|
_ = unexportedInStruct.ch
|
||||||
|
_ = unexportedInStruct.unsafePtr
|
||||||
|
_ = unexportedInStruct.mapStructStr[structKey{1}]
|
||||||
|
_, _ = json.Marshal(unexportedInStruct) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(unexportedInStruct) // struct containing unsafe but unexported fields is safe
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalSafeStructWithOmittedFieldsWithNoSafe contains a struct with omitted, unsafe fields.
|
||||||
|
func JSONMarshalSaveStructWithOmittedFieldsWithNoSafe() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var omitInStruct struct {
|
||||||
|
Bool bool // safe exported
|
||||||
|
|
||||||
|
F64 float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
F64Ptr *float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
F64Slice []float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
F64Array [10]float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
MapStrF64 map[string]float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
MapEIStr map[interface{}]string `json:"-"` // unsafe exported but omitted
|
||||||
|
Number json.Number `json:"-"` // unsafe exported but omitted
|
||||||
|
NumberPtr *json.Number `json:"-"` // unsafe exported but omitted
|
||||||
|
NumberSlice []json.Number `json:"-"` // unsafe exported but omitted
|
||||||
|
MapNumberStr map[json.Number]string `json:"-"` // unsafe exported but omitted
|
||||||
|
Ei interface{} `json:"-"` // unsafe exported but omitted
|
||||||
|
Stringer fmt.Stringer `json:"-"` // unsafe exported but omitted
|
||||||
|
Mt marshalText `json:"-"` // unsafe exported but omitted
|
||||||
|
MapMarshalTextString map[marshalText]string `json:"-"` // unsafe exported but omitted
|
||||||
|
ExportedStruct ExportedUnsafeAndInvalidStruct `json:"-"` // unsafe exported but omitted
|
||||||
|
ExportedStructPtr *ExportedUnsafeAndInvalidStruct `json:"-"` // unsafe exported but omitted
|
||||||
|
|
||||||
|
C128 complex128 `json:"-"` // invalid exported but omitted
|
||||||
|
C128Slice []complex128 `json:"-"` // invalid exported but omitted
|
||||||
|
C128Array [10]complex128 `json:"-"` // invalid exported but omitted
|
||||||
|
MapBoolStr map[bool]string `json:"-"` // invalid exported but omitted
|
||||||
|
MapF64Str map[float64]string `json:"-"` // invalid exported but omitted
|
||||||
|
F func() `json:"-"` // invalid exported but omitted
|
||||||
|
Ch chan struct{} `json:"-"` // invalid exported but omitted
|
||||||
|
UnsafePtr unsafe.Pointer `json:"-"` // invalid exported but omitted
|
||||||
|
MapStructStr map[structKey]string `json:"-"` // invalid exported but omitted
|
||||||
|
}
|
||||||
|
_ = omitInStruct.MapStructStr[structKey{1}]
|
||||||
|
_, _ = json.Marshal(omitInStruct) // ERROR "Error return value of `encoding/json.Marshal` is not checked"
|
||||||
|
_, err = json.Marshal(omitInStruct) // struct containing unsafe but omitted, exported fields is safe and check-error-free-encoding is false
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalUnsafeTypes contains a multitude of test cases to marshal different combinations of types to JSON,
|
||||||
|
// that can potentially lead to json.Marshal returning an error.
|
||||||
|
func JSONMarshalUnsafeTypes() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var f32 float32
|
||||||
|
json.Marshal(f32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, _ = json.Marshal(f32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(f32) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f64 float64
|
||||||
|
_, _ = json.Marshal(f64) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(f64) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f32Slice []float32
|
||||||
|
_, _ = json.Marshal(f32Slice) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(f32Slice) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f64Slice []float64
|
||||||
|
_, _ = json.Marshal(f64Slice) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(f64Slice) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f32Array [10]float32
|
||||||
|
_, _ = json.Marshal(f32Array) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(f32Array) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f64Array [10]float64
|
||||||
|
_, _ = json.Marshal(f64Array) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(f64Array) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrF32 struct {
|
||||||
|
F32 *float32
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrF32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(structPtrF32) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrF64 struct {
|
||||||
|
F64 *float64
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrF64) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(structPtrF64) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrF32 map[string]float32
|
||||||
|
_, _ = json.Marshal(mapStrF32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(mapStrF32) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrF64 map[string]float64
|
||||||
|
_, _ = json.Marshal(mapStrF64) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(mapStrF64) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapEIStr map[interface{}]string
|
||||||
|
_, _ = json.Marshal(mapEIStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` as map key found"
|
||||||
|
_, err = json.Marshal(mapEIStr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStringerStr map[fmt.Stringer]string
|
||||||
|
_, _ = json.Marshal(mapStringerStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `fmt.Stringer` as map key found"
|
||||||
|
_, err = json.Marshal(mapStringerStr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var number json.Number
|
||||||
|
_, _ = json.Marshal(number) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` found"
|
||||||
|
_, err = json.Marshal(number) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var numberSlice []json.Number
|
||||||
|
_, _ = json.Marshal(numberSlice) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` found"
|
||||||
|
_, err = json.Marshal(numberSlice) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapNumberStr map[json.Number]string
|
||||||
|
_, _ = json.Marshal(mapNumberStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` as map key found"
|
||||||
|
_, err = json.Marshal(mapNumberStr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrNumber map[string]json.Number
|
||||||
|
_, _ = json.Marshal(mapStrNumber) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` found"
|
||||||
|
_, err = json.Marshal(mapStrNumber) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ei interface{}
|
||||||
|
_, _ = json.Marshal(ei) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found"
|
||||||
|
_, err = json.Marshal(ei) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var eiptr *interface{}
|
||||||
|
_, _ = json.Marshal(eiptr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `*interface{}` found"
|
||||||
|
_, err = json.Marshal(eiptr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var stringer fmt.Stringer
|
||||||
|
_, _ = json.Marshal(stringer) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `fmt.Stringer` found"
|
||||||
|
_, err = json.Marshal(stringer) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structWithEmptyInterface struct {
|
||||||
|
EmptyInterface interface{}
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structWithEmptyInterface) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found"
|
||||||
|
_, err = json.Marshal(structWithEmptyInterface) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mt marshalText
|
||||||
|
_, _ = json.Marshal(mt) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `[a-z-]+.marshalText` found"
|
||||||
|
_, err = json.Marshal(mt) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapMarshalTextString map[marshalText]string
|
||||||
|
_, _ = json.Marshal(mapMarshalTextString) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `[a-z-]+.marshalText` as map key found"
|
||||||
|
_, err = json.Marshal(mapMarshalTextString) // err is checked
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalInvalidTypes contains a multitude of test cases to marshal different combinations of types to JSON,
|
||||||
|
// that are invalid and not supported by json.Marshal, that is they will always return an error, if these types used
|
||||||
|
// with json.Marshal.
|
||||||
|
func JSONMarshalInvalidTypes() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var c64 complex64
|
||||||
|
json.Marshal(c64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, _ = json.Marshal(c64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(c64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var c128 complex128
|
||||||
|
_, _ = json.Marshal(c128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(c128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var sliceC64 []complex64
|
||||||
|
_, _ = json.Marshal(sliceC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(sliceC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var sliceC128 []complex128
|
||||||
|
_, _ = json.Marshal(sliceC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(sliceC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var arrayC64 []complex64
|
||||||
|
_, _ = json.Marshal(arrayC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(arrayC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var arrayC128 []complex128
|
||||||
|
_, _ = json.Marshal(arrayC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(arrayC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrC64 struct {
|
||||||
|
C64 *complex64
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(structPtrC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrC128 struct {
|
||||||
|
C128 *complex128
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(structPtrC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapBoolStr map[bool]string
|
||||||
|
_, _ = json.Marshal(mapBoolStr) // ERROR "`encoding/json.Marshal` for unsupported type `bool` as map key found"
|
||||||
|
_, err = json.Marshal(mapBoolStr) // ERROR "`encoding/json.Marshal` for unsupported type `bool` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapF32Str map[float32]string
|
||||||
|
_, _ = json.Marshal(mapF32Str) // ERROR "`encoding/json.Marshal` for unsupported type `float32` as map key found"
|
||||||
|
_, err = json.Marshal(mapF32Str) // ERROR "`encoding/json.Marshal` for unsupported type `float32` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapF64Str map[float64]string
|
||||||
|
_, _ = json.Marshal(mapF64Str) // ERROR "`encoding/json.Marshal` for unsupported type `float64` as map key found"
|
||||||
|
_, err = json.Marshal(mapF64Str) // ERROR "`encoding/json.Marshal` for unsupported type `float64` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapC64Str map[complex64]string
|
||||||
|
_, _ = json.Marshal(mapC64Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` as map key found"
|
||||||
|
_, err = json.Marshal(mapC64Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapC128Str map[complex128]string
|
||||||
|
_, _ = json.Marshal(mapC128Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` as map key found"
|
||||||
|
_, err = json.Marshal(mapC128Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
mapStructStr := map[structKey]string{structKey{1}: "str"}
|
||||||
|
_, _ = json.Marshal(mapStructStr) // ERROR "`encoding/json.Marshal` for unsupported type `[a-z-]+.structKey` as map key found"
|
||||||
|
_, err = json.Marshal(mapStructStr) // ERROR "`encoding/json.Marshal` for unsupported type `[a-z-]+.structKey` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
f := func() {}
|
||||||
|
_, _ = json.Marshal(f) // ERROR "`encoding/json.Marshal` for unsupported type `func\\(\\)` found"
|
||||||
|
_, err = json.Marshal(f) // ERROR "`encoding/json.Marshal` for unsupported type `func\\(\\)` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ch chan struct{} = make(chan struct{})
|
||||||
|
_, _ = json.Marshal(ch) // ERROR "`encoding/json.Marshal` for unsupported type `chan struct{}` found"
|
||||||
|
_, err = json.Marshal(ch) // ERROR "`encoding/json.Marshal` for unsupported type `chan struct{}` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var unsafePtr unsafe.Pointer
|
||||||
|
_, _ = json.Marshal(unsafePtr) // ERROR "`encoding/json.Marshal` for unsupported type `unsafe.Pointer` found"
|
||||||
|
_, err = json.Marshal(unsafePtr) // ERROR "`encoding/json.Marshal` for unsupported type `unsafe.Pointer` found"
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotJSONMarshal contains other go ast node types, that are not considered by errchkjson
|
||||||
|
func NotJSONMarshal() {
|
||||||
|
s := fmt.Sprintln("I am not considered by errchkjson")
|
||||||
|
_ = s
|
||||||
|
f := func() bool { return false }
|
||||||
|
_ = f()
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalStructWithoutExportedFields contains a struct without exported fields.
|
||||||
|
func JSONMarshalStructWithoutExportedFields() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var withoutExportedFields struct {
|
||||||
|
privateField bool
|
||||||
|
ExportedButOmittedField bool `json:"-"`
|
||||||
|
}
|
||||||
|
_, err = json.Marshal(withoutExportedFields) // want "Error argument passed to `encoding/json.Marshal` does not contain any exported field"
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalStructWithoutExportedFields contains a struct without exported fields.
|
||||||
|
func JSONMarshalStructWithNestedStructWithoutExportedFields() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var withNestedStructWithoutExportedFields struct {
|
||||||
|
ExportedStruct struct {
|
||||||
|
privatField bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = json.Marshal(withNestedStructWithoutExportedFields)
|
||||||
|
_ = err
|
||||||
|
}
|
616
test/testdata/errchkjson_check_error_free_encoding.go
vendored
Normal file
616
test/testdata/errchkjson_check_error_free_encoding.go
vendored
Normal file
@ -0,0 +1,616 @@
|
|||||||
|
// args: -Eerrchkjson
|
||||||
|
// config_path: testdata/configs/errchkjson_check_error_free_encoding.yml
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type marshalText struct{}
|
||||||
|
|
||||||
|
func (mt marshalText) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(`mt`), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ encoding.TextMarshaler = marshalText(struct{}{})
|
||||||
|
|
||||||
|
// JSONMarshalSafeTypes contains a multitude of test cases to marshal different combinations of types to JSON,
|
||||||
|
// that are safe, that is, they will never return an error, if these types are marshaled to JSON.
|
||||||
|
func JSONMarshalSafeTypes() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
_, _ = json.Marshal(nil) // nil is safe
|
||||||
|
json.Marshal(nil) // nil is safe
|
||||||
|
_, err = json.Marshal(nil) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
_, _ = json.MarshalIndent(nil, "", " ") // nil is safe
|
||||||
|
json.MarshalIndent(nil, "", " ") // nil is safe
|
||||||
|
_, err = json.MarshalIndent(nil, "", " ") // ERROR "Error return value of `encoding/json.MarshalIndent` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
enc := json.NewEncoder(ioutil.Discard)
|
||||||
|
_ = enc.Encode(nil) // nil is safe
|
||||||
|
enc.Encode(nil) // nil is safe
|
||||||
|
err = enc.Encode(nil) // ERROR "Error return value of `\\([*]encoding/json.Encoder\\).Encode` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var b bool
|
||||||
|
_, _ = json.Marshal(b) // bool is safe
|
||||||
|
_, err = json.Marshal(b) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i int
|
||||||
|
_, _ = json.Marshal(i) // int is safe
|
||||||
|
_, err = json.Marshal(i) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i8 int8
|
||||||
|
_, _ = json.Marshal(i8) // int8 is safe
|
||||||
|
_, err = json.Marshal(i8) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i16 int16
|
||||||
|
_, _ = json.Marshal(i16) // int16 is safe
|
||||||
|
_, err = json.Marshal(i16) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i32 int32
|
||||||
|
_, _ = json.Marshal(i32) // int32 / rune is safe
|
||||||
|
_, err = json.Marshal(i32) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var i64 int64
|
||||||
|
_, _ = json.Marshal(i64) // int64 is safe
|
||||||
|
_, err = json.Marshal(i64) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui uint
|
||||||
|
_, _ = json.Marshal(ui) // uint is safe
|
||||||
|
_, err = json.Marshal(ui) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui8 uint8
|
||||||
|
_, _ = json.Marshal(ui8) // uint8 / byte is safe
|
||||||
|
_, err = json.Marshal(ui8) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui16 uint16
|
||||||
|
_, _ = json.Marshal(ui16) // uint16 is safe
|
||||||
|
_, err = json.Marshal(ui16) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui32 uint32
|
||||||
|
_, _ = json.Marshal(ui32) // uint32 / rune is safe
|
||||||
|
_, err = json.Marshal(ui32) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ui64 uint64
|
||||||
|
_, _ = json.Marshal(ui64) // uint64 is safe
|
||||||
|
_, err = json.Marshal(ui64) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var uiptr uintptr
|
||||||
|
_, _ = json.Marshal(uiptr) // uintptr is safe
|
||||||
|
_, err = json.Marshal(uiptr) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var str string
|
||||||
|
_, _ = json.Marshal(str) // string is safe
|
||||||
|
_, err = json.Marshal(str) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var strSlice []string
|
||||||
|
_, _ = json.Marshal(strSlice) // []string is safe
|
||||||
|
_, err = json.Marshal(strSlice) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var intSlice []int
|
||||||
|
_, _ = json.Marshal(intSlice) // []int is safe
|
||||||
|
_, err = json.Marshal(intSlice) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var boolSlice []bool
|
||||||
|
_, _ = json.Marshal(boolSlice) // []bool is safe
|
||||||
|
_, err = json.Marshal(boolSlice) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var strArray [10]string
|
||||||
|
_, _ = json.Marshal(strArray) // [10]string is safe
|
||||||
|
_, err = json.Marshal(strArray) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var intArray [10]int
|
||||||
|
_, _ = json.Marshal(intArray) // [10]int is safe
|
||||||
|
_, err = json.Marshal(intArray) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var boolArray [10]bool
|
||||||
|
_, _ = json.Marshal(boolArray) // [10]bool is safe
|
||||||
|
_, err = json.Marshal(boolArray) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var basicStruct struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
Int8 int8
|
||||||
|
Int16 int16
|
||||||
|
Int32 int32 // also rune
|
||||||
|
Int64 int64
|
||||||
|
Uint uint
|
||||||
|
Uint8 uint8 // also byte
|
||||||
|
Uint16 uint16
|
||||||
|
Uint32 uint32
|
||||||
|
Uint64 uint64
|
||||||
|
Uintptr uintptr
|
||||||
|
String string
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(basicStruct) // struct containing only safe basic types is safe
|
||||||
|
_, err = json.Marshal(basicStruct) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ptrStruct struct {
|
||||||
|
Bool *bool
|
||||||
|
Int *int
|
||||||
|
Int8 *int8
|
||||||
|
Int16 *int16
|
||||||
|
Int32 *int32
|
||||||
|
Int64 *int64
|
||||||
|
Uint *uint
|
||||||
|
Uint8 *uint8
|
||||||
|
Uint16 *uint16
|
||||||
|
Uint32 *uint32
|
||||||
|
Uint64 *uint64
|
||||||
|
Uintptr *uintptr
|
||||||
|
String *string
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(ptrStruct) // struct containing pointer to only safe basic types is safe
|
||||||
|
_, err = json.Marshal(ptrStruct) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrStr map[string]string
|
||||||
|
_, _ = json.Marshal(mapStrStr) // map[string]string is safe
|
||||||
|
_, err = json.Marshal(mapStrStr) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrInt map[string]int
|
||||||
|
_, _ = json.Marshal(mapStrInt) // map[string]int is safe
|
||||||
|
_, err = json.Marshal(mapStrInt) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrBool map[string]bool
|
||||||
|
_, _ = json.Marshal(mapStrBool) // map[string]bool is safe
|
||||||
|
_, err = json.Marshal(mapStrBool) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapIntStr map[int]string
|
||||||
|
_, _ = json.Marshal(mapIntStr) // map[int]string is safe
|
||||||
|
_, err = json.Marshal(mapIntStr) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapIntInt map[int]int
|
||||||
|
_, _ = json.Marshal(mapIntInt) // map[int]int is safe
|
||||||
|
_, err = json.Marshal(mapIntInt) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapIntBool map[int]bool
|
||||||
|
_, _ = json.Marshal(mapIntBool) // map[int]bool is safe
|
||||||
|
_, err = json.Marshal(mapIntBool) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
type innerStruct struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
String string
|
||||||
|
|
||||||
|
StrSlice []string
|
||||||
|
IntSlice []int
|
||||||
|
BoolSlice []bool
|
||||||
|
|
||||||
|
StrArray [10]string
|
||||||
|
IntArray [10]int
|
||||||
|
BoolArray [10]bool
|
||||||
|
|
||||||
|
MapStrStr map[string]string
|
||||||
|
MapStrInt map[string]int
|
||||||
|
MapStrBool map[string]bool
|
||||||
|
|
||||||
|
MapIntStr map[int]string
|
||||||
|
MapIntInt map[int]int
|
||||||
|
MapIntBool map[int]bool
|
||||||
|
}
|
||||||
|
var outerStruct struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
String string
|
||||||
|
|
||||||
|
StrSlice []string
|
||||||
|
IntSlice []int
|
||||||
|
BoolSlice []bool
|
||||||
|
|
||||||
|
StrArray [10]string
|
||||||
|
IntArray [10]int
|
||||||
|
BoolArray [10]bool
|
||||||
|
|
||||||
|
MapStrStr map[string]string
|
||||||
|
MapStrInt map[string]int
|
||||||
|
MapStrBool map[string]bool
|
||||||
|
|
||||||
|
MapIntStr map[int]string
|
||||||
|
MapIntInt map[int]int
|
||||||
|
MapIntBool map[int]bool
|
||||||
|
|
||||||
|
InnerStruct innerStruct
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(outerStruct) // struct with only safe types
|
||||||
|
_, err = json.Marshal(outerStruct) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
structKey struct{ id int }
|
||||||
|
ExportedUnsafeAndInvalidStruct struct { // unsafe unexported but omitted
|
||||||
|
F64 float64
|
||||||
|
F64Ptr *float64
|
||||||
|
F64Slice []float64
|
||||||
|
F64Array [10]float64
|
||||||
|
MapStrF64 map[string]float64
|
||||||
|
MapEIStr map[interface{}]string
|
||||||
|
Number json.Number
|
||||||
|
NumberPtr *json.Number
|
||||||
|
NumberSlice []json.Number
|
||||||
|
MapNumberStr map[json.Number]string
|
||||||
|
Ei interface{}
|
||||||
|
Stringer fmt.Stringer
|
||||||
|
Mt marshalText
|
||||||
|
MapMarshalTextString map[marshalText]string
|
||||||
|
|
||||||
|
C128 complex128
|
||||||
|
C128Ptr *complex128
|
||||||
|
C128Slice []complex128
|
||||||
|
C128Array [10]complex128
|
||||||
|
MapBoolStr map[bool]string
|
||||||
|
MapF64Str map[float64]string
|
||||||
|
F func()
|
||||||
|
Ch chan struct{}
|
||||||
|
UnsafePtr unsafe.Pointer
|
||||||
|
MapStructStr map[structKey]string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// JSONMarshalSaveStructWithUnexportedFields contains a struct with unexported, unsafe fields.
|
||||||
|
func JSONMarshalSaveStructWithUnexportedFields() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var unexportedInStruct struct {
|
||||||
|
Bool bool // safe exported
|
||||||
|
|
||||||
|
f64 float64 // unsafe unexported
|
||||||
|
f64Ptr *float64 // unsafe unexported
|
||||||
|
f64Slice []float64 // unsafe unexported
|
||||||
|
f64Array [10]float64 // unsafe unexported
|
||||||
|
mapStrF64 map[string]float64 // unsafe unexported
|
||||||
|
mapEIStr map[interface{}]string // unsafe unexported
|
||||||
|
number json.Number // unsafe unexported
|
||||||
|
numberPtr *json.Number // unsafe unexported
|
||||||
|
numberSlice []json.Number // unsafe unexported
|
||||||
|
mapNumberStr map[json.Number]string // unsafe unexported
|
||||||
|
ei interface{} // unsafe unexported
|
||||||
|
stringer fmt.Stringer // unsafe unexported
|
||||||
|
mt marshalText // unsafe unexported
|
||||||
|
mapMarshalTextString map[marshalText]string // unsafe unexported
|
||||||
|
unexportedStruct ExportedUnsafeAndInvalidStruct // unsafe unexported
|
||||||
|
unexportedStructPtr *ExportedUnsafeAndInvalidStruct // unsafe unexported
|
||||||
|
|
||||||
|
c128 complex128 // invalid unexported
|
||||||
|
c128Slice []complex128 // invalid unexported
|
||||||
|
c128Array [10]complex128 // invalid unexported
|
||||||
|
mapBoolStr map[bool]string // invalid unexported
|
||||||
|
mapF64Str map[float64]string // invalid unexported
|
||||||
|
f func() // invalid unexported
|
||||||
|
ch chan struct{} // invalid unexported
|
||||||
|
unsafePtr unsafe.Pointer // invalid unexported
|
||||||
|
mapStructStr map[structKey]string // invalid unexported
|
||||||
|
}
|
||||||
|
_ = unexportedInStruct.f64
|
||||||
|
_ = unexportedInStruct.f64Ptr
|
||||||
|
_ = unexportedInStruct.f64Slice
|
||||||
|
_ = unexportedInStruct.f64Array
|
||||||
|
_ = unexportedInStruct.mapStrF64
|
||||||
|
_ = unexportedInStruct.mapEIStr
|
||||||
|
_ = unexportedInStruct.number
|
||||||
|
_ = unexportedInStruct.numberPtr
|
||||||
|
_ = unexportedInStruct.numberSlice
|
||||||
|
_ = unexportedInStruct.mapNumberStr
|
||||||
|
_ = unexportedInStruct.ei
|
||||||
|
_ = unexportedInStruct.stringer
|
||||||
|
_ = unexportedInStruct.mt
|
||||||
|
_ = unexportedInStruct.mapMarshalTextString
|
||||||
|
_ = unexportedInStruct.unexportedStruct
|
||||||
|
_ = unexportedInStruct.unexportedStructPtr
|
||||||
|
|
||||||
|
_ = unexportedInStruct.c128
|
||||||
|
_ = unexportedInStruct.c128Slice
|
||||||
|
_ = unexportedInStruct.c128Array
|
||||||
|
_ = unexportedInStruct.mapBoolStr
|
||||||
|
_ = unexportedInStruct.mapF64Str
|
||||||
|
_ = unexportedInStruct.f
|
||||||
|
_ = unexportedInStruct.ch
|
||||||
|
_ = unexportedInStruct.unsafePtr
|
||||||
|
_ = unexportedInStruct.mapStructStr[structKey{1}]
|
||||||
|
_, _ = json.Marshal(unexportedInStruct) // struct containing unsafe but unexported fields is safe
|
||||||
|
_, err = json.Marshal(unexportedInStruct) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalSaveStructWithOmittedFields contains a struct with omitted, unsafe fields.
|
||||||
|
func JSONMarshalSaveStructWithOmittedFields() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var omitInStruct struct {
|
||||||
|
Bool bool // safe exported
|
||||||
|
|
||||||
|
F64 float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
F64Ptr *float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
F64Slice []float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
F64Array [10]float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
MapStrF64 map[string]float64 `json:"-"` // unsafe exported but omitted
|
||||||
|
MapEIStr map[interface{}]string `json:"-"` // unsafe exported but omitted
|
||||||
|
Number json.Number `json:"-"` // unsafe exported but omitted
|
||||||
|
NumberPtr *json.Number `json:"-"` // unsafe exported but omitted
|
||||||
|
NumberSlice []json.Number `json:"-"` // unsafe exported but omitted
|
||||||
|
MapNumberStr map[json.Number]string `json:"-"` // unsafe exported but omitted
|
||||||
|
Ei interface{} `json:"-"` // unsafe exported but omitted
|
||||||
|
Stringer fmt.Stringer `json:"-"` // unsafe exported but omitted
|
||||||
|
Mt marshalText `json:"-"` // unsafe exported but omitted
|
||||||
|
MapMarshalTextString map[marshalText]string `json:"-"` // unsafe exported but omitted
|
||||||
|
ExportedStruct ExportedUnsafeAndInvalidStruct `json:"-"` // unsafe exported but omitted
|
||||||
|
ExportedStructPtr *ExportedUnsafeAndInvalidStruct `json:"-"` // unsafe exported but omitted
|
||||||
|
|
||||||
|
C128 complex128 `json:"-"` // invalid exported but omitted
|
||||||
|
C128Slice []complex128 `json:"-"` // invalid exported but omitted
|
||||||
|
C128Array [10]complex128 `json:"-"` // invalid exported but omitted
|
||||||
|
MapBoolStr map[bool]string `json:"-"` // invalid exported but omitted
|
||||||
|
MapF64Str map[float64]string `json:"-"` // invalid exported but omitted
|
||||||
|
F func() `json:"-"` // invalid exported but omitted
|
||||||
|
Ch chan struct{} `json:"-"` // invalid exported but omitted
|
||||||
|
UnsafePtr unsafe.Pointer `json:"-"` // invalid exported but omitted
|
||||||
|
MapStructStr map[structKey]string `json:"-"` // invalid exported but omitted
|
||||||
|
}
|
||||||
|
_ = omitInStruct.MapStructStr[structKey{1}]
|
||||||
|
_, _ = json.Marshal(omitInStruct) // struct containing unsafe but omitted, exported fields is safe
|
||||||
|
_, err = json.Marshal(omitInStruct) // ERROR "Error return value of `encoding/json.Marshal` is checked but passed argument is safe"
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalUnsafeTypes contains a multitude of test cases to marshal different combinations of types to JSON,
|
||||||
|
// that can potentially lead to json.Marshal returning an error.
|
||||||
|
func JSONMarshalUnsafeTypes() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var f32 float32
|
||||||
|
json.Marshal(f32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, _ = json.Marshal(f32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(f32) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f64 float64
|
||||||
|
_, _ = json.Marshal(f64) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(f64) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f32Slice []float32
|
||||||
|
_, _ = json.Marshal(f32Slice) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(f32Slice) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f64Slice []float64
|
||||||
|
_, _ = json.Marshal(f64Slice) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(f64Slice) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f32Array [10]float32
|
||||||
|
_, _ = json.Marshal(f32Array) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(f32Array) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var f64Array [10]float64
|
||||||
|
_, _ = json.Marshal(f64Array) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(f64Array) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrF32 struct {
|
||||||
|
F32 *float32
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrF32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(structPtrF32) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrF64 struct {
|
||||||
|
F64 *float64
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrF64) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(structPtrF64) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrF32 map[string]float32
|
||||||
|
_, _ = json.Marshal(mapStrF32) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float32` found"
|
||||||
|
_, err = json.Marshal(mapStrF32) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrF64 map[string]float64
|
||||||
|
_, _ = json.Marshal(mapStrF64) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `float64` found"
|
||||||
|
_, err = json.Marshal(mapStrF64) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapEIStr map[interface{}]string
|
||||||
|
_, _ = json.Marshal(mapEIStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` as map key found"
|
||||||
|
_, err = json.Marshal(mapEIStr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStringerStr map[fmt.Stringer]string
|
||||||
|
_, _ = json.Marshal(mapStringerStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `fmt.Stringer` as map key found"
|
||||||
|
_, err = json.Marshal(mapStringerStr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var number json.Number
|
||||||
|
_, _ = json.Marshal(number) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` found"
|
||||||
|
_, err = json.Marshal(number) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var numberSlice []json.Number
|
||||||
|
_, _ = json.Marshal(numberSlice) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` found"
|
||||||
|
_, err = json.Marshal(numberSlice) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapNumberStr map[json.Number]string
|
||||||
|
_, _ = json.Marshal(mapNumberStr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` as map key found"
|
||||||
|
_, err = json.Marshal(mapNumberStr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapStrNumber map[string]json.Number
|
||||||
|
_, _ = json.Marshal(mapStrNumber) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `encoding/json.Number` found"
|
||||||
|
_, err = json.Marshal(mapStrNumber) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ei interface{}
|
||||||
|
_, _ = json.Marshal(ei) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found"
|
||||||
|
_, err = json.Marshal(ei) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var eiptr *interface{}
|
||||||
|
_, _ = json.Marshal(eiptr) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `*interface{}` found"
|
||||||
|
_, err = json.Marshal(eiptr) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var stringer fmt.Stringer
|
||||||
|
_, _ = json.Marshal(stringer) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `fmt.Stringer` found"
|
||||||
|
_, err = json.Marshal(stringer) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structWithEmptyInterface struct {
|
||||||
|
EmptyInterface interface{}
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structWithEmptyInterface) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found"
|
||||||
|
_, err = json.Marshal(structWithEmptyInterface) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mt marshalText
|
||||||
|
_, _ = json.Marshal(mt) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `[a-z-]+.marshalText` found"
|
||||||
|
_, err = json.Marshal(mt) // err is checked
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapMarshalTextString map[marshalText]string
|
||||||
|
_, _ = json.Marshal(mapMarshalTextString) // ERROR "Error return value of `encoding/json.Marshal` is not checked: unsafe type `[a-z-]+.marshalText` as map key found"
|
||||||
|
_, err = json.Marshal(mapMarshalTextString) // err is checked
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalInvalidTypes contains a multitude of test cases to marshal different combinations of types to JSON,
|
||||||
|
// that are invalid and not supported by json.Marshal, that is they will always return an error, if these types used
|
||||||
|
// with json.Marshal.
|
||||||
|
func JSONMarshalInvalidTypes() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var c64 complex64
|
||||||
|
json.Marshal(c64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, _ = json.Marshal(c64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(c64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var c128 complex128
|
||||||
|
_, _ = json.Marshal(c128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(c128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var sliceC64 []complex64
|
||||||
|
_, _ = json.Marshal(sliceC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(sliceC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var sliceC128 []complex128
|
||||||
|
_, _ = json.Marshal(sliceC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(sliceC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var arrayC64 []complex64
|
||||||
|
_, _ = json.Marshal(arrayC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(arrayC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var arrayC128 []complex128
|
||||||
|
_, _ = json.Marshal(arrayC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(arrayC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrC64 struct {
|
||||||
|
C64 *complex64
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_, err = json.Marshal(structPtrC64) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var structPtrC128 struct {
|
||||||
|
C128 *complex128
|
||||||
|
}
|
||||||
|
_, _ = json.Marshal(structPtrC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_, err = json.Marshal(structPtrC128) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapBoolStr map[bool]string
|
||||||
|
_, _ = json.Marshal(mapBoolStr) // ERROR "`encoding/json.Marshal` for unsupported type `bool` as map key found"
|
||||||
|
_, err = json.Marshal(mapBoolStr) // ERROR "`encoding/json.Marshal` for unsupported type `bool` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapF32Str map[float32]string
|
||||||
|
_, _ = json.Marshal(mapF32Str) // ERROR "`encoding/json.Marshal` for unsupported type `float32` as map key found"
|
||||||
|
_, err = json.Marshal(mapF32Str) // ERROR "`encoding/json.Marshal` for unsupported type `float32` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapF64Str map[float64]string
|
||||||
|
_, _ = json.Marshal(mapF64Str) // ERROR "`encoding/json.Marshal` for unsupported type `float64` as map key found"
|
||||||
|
_, err = json.Marshal(mapF64Str) // ERROR "`encoding/json.Marshal` for unsupported type `float64` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapC64Str map[complex64]string
|
||||||
|
_, _ = json.Marshal(mapC64Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` as map key found"
|
||||||
|
_, err = json.Marshal(mapC64Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex64` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var mapC128Str map[complex128]string
|
||||||
|
_, _ = json.Marshal(mapC128Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` as map key found"
|
||||||
|
_, err = json.Marshal(mapC128Str) // ERROR "`encoding/json.Marshal` for unsupported type `complex128` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
mapStructStr := map[structKey]string{structKey{1}: "str"}
|
||||||
|
_, _ = json.Marshal(mapStructStr) // ERROR "`encoding/json.Marshal` for unsupported type `[a-z-]+.structKey` as map key found"
|
||||||
|
_, err = json.Marshal(mapStructStr) // ERROR "`encoding/json.Marshal` for unsupported type `[a-z-]+.structKey` as map key found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
f := func() {}
|
||||||
|
_, _ = json.Marshal(f) // ERROR "`encoding/json.Marshal` for unsupported type `func\\(\\)` found"
|
||||||
|
_, err = json.Marshal(f) // ERROR "`encoding/json.Marshal` for unsupported type `func\\(\\)` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var ch chan struct{} = make(chan struct{})
|
||||||
|
_, _ = json.Marshal(ch) // ERROR "`encoding/json.Marshal` for unsupported type `chan struct{}` found"
|
||||||
|
_, err = json.Marshal(ch) // ERROR "`encoding/json.Marshal` for unsupported type `chan struct{}` found"
|
||||||
|
_ = err
|
||||||
|
|
||||||
|
var unsafePtr unsafe.Pointer
|
||||||
|
_, _ = json.Marshal(unsafePtr) // ERROR "`encoding/json.Marshal` for unsupported type `unsafe.Pointer` found"
|
||||||
|
_, err = json.Marshal(unsafePtr) // ERROR "`encoding/json.Marshal` for unsupported type `unsafe.Pointer` found"
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotJSONMarshal contains other go ast node types, that are not considered by errchkjson
|
||||||
|
func NotJSONMarshal() {
|
||||||
|
s := fmt.Sprintln("I am not considered by errchkjson")
|
||||||
|
_ = s
|
||||||
|
f := func() bool { return false }
|
||||||
|
_ = f()
|
||||||
|
}
|
28
test/testdata/errchkjson_no_exported.go
vendored
Normal file
28
test/testdata/errchkjson_no_exported.go
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// args: -Eerrchkjson
|
||||||
|
// config_path: testdata/configs/errchkjson_no_exported.yml
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// JSONMarshalStructWithoutExportedFields contains a struct without exported fields.
|
||||||
|
func JSONMarshalStructWithoutExportedFields() {
|
||||||
|
var withoutExportedFields struct {
|
||||||
|
privateField bool
|
||||||
|
ExportedButOmittedField bool `json:"-"`
|
||||||
|
}
|
||||||
|
_, err := json.Marshal(withoutExportedFields) // ERROR "Error argument passed to `encoding/json.Marshal` does not contain any exported field"
|
||||||
|
_ = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONMarshalStructWithNestedStructWithoutExportedFields contains a struct without exported fields.
|
||||||
|
func JSONMarshalStructWithNestedStructWithoutExportedFields() {
|
||||||
|
var withNestedStructWithoutExportedFields struct {
|
||||||
|
ExportedStruct struct {
|
||||||
|
privatField bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := json.Marshal(withNestedStructWithoutExportedFields)
|
||||||
|
_ = err
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user