aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/config/config.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2021-04-20 14:11:30 +0200
committerDmitry Vyukov <dvyukov@google.com>2021-04-28 07:08:41 +0200
commitde0456bb5ab22e568b8a3ffcce6bf85e2a7de164 (patch)
tree1d8603e4ee455b2c6c4e5ea36d42e28ce7977b1c /pkg/config/config.go
parent805b5003de8c474f5d317a67f739597ebc78fcca (diff)
pkg/config: use DisallowUnknownFields
DisallowUnknownFields was added in Go 1.10, remove our custom machinery for checking unknown fields.
Diffstat (limited to 'pkg/config/config.go')
-rw-r--r--pkg/config/config.go88
1 files changed, 4 insertions, 84 deletions
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 49d030499..a4f56c225 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -4,11 +4,10 @@
package config
import (
+ "bytes"
"encoding/json"
"fmt"
"io/ioutil"
- "reflect"
- "strings"
"github.com/google/syzkaller/pkg/osutil"
)
@@ -25,10 +24,9 @@ func LoadFile(filename string, cfg interface{}) error {
}
func LoadData(data []byte, cfg interface{}) error {
- if err := checkUnknownFields(data, reflect.ValueOf(cfg).Type()); err != nil {
- return err
- }
- if err := json.Unmarshal(data, cfg); err != nil {
+ dec := json.NewDecoder(bytes.NewReader(data))
+ dec.DisallowUnknownFields()
+ if err := dec.Decode(cfg); err != nil {
return fmt.Errorf("failed to parse config file: %v", err)
}
return nil
@@ -45,81 +43,3 @@ func SaveFile(filename string, cfg interface{}) error {
func SaveData(cfg interface{}) ([]byte, error) {
return json.MarshalIndent(cfg, "", "\t")
}
-
-func checkUnknownFields(data []byte, typ reflect.Type) error {
- if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Struct {
- return fmt.Errorf("config type is not pointer to struct")
- }
- return checkUnknownFieldsRec(data, "", typ)
-}
-
-func checkUnknownFieldsRec(data []byte, prefix string, typ reflect.Type) error {
- if typ.Kind() == reflect.Ptr {
- typ = typ.Elem()
- }
- if typ.Kind() != reflect.Struct {
- return fmt.Errorf("config type is not pointer to struct")
- }
- fields := make(map[string]reflect.Type)
- for i := 0; i < typ.NumField(); i++ {
- field := typ.Field(i)
- tag := field.Tag.Get("json")
- tag = strings.TrimSuffix(tag, ",omitempty")
- if tag == "-" {
- continue
- }
- name := strings.ToLower(field.Name)
- if tag != "" {
- if tag != strings.ToLower(tag) {
- return fmt.Errorf("json tag on '%v%v' should be lower-case", prefix, name)
- }
- name = tag
- }
- fields[name] = field.Type
- }
- f := make(map[string]interface{})
- if err := json.Unmarshal(data, &f); err != nil {
- return fmt.Errorf("failed to parse config file: %v", err)
- }
- for k, v := range f {
- field, ok := fields[strings.ToLower(k)]
- if !ok {
- return fmt.Errorf("unknown field '%v%v' in config", prefix, k)
- }
- if v != nil && field.Kind() == reflect.Slice &&
- (field.PkgPath() != "encoding/json" || field.Name() != "RawMessage") {
- vv := reflect.ValueOf(v)
- if vv.Type().Kind() != reflect.Slice {
- return fmt.Errorf("bad json array type '%v%v'", prefix, k)
- }
- for i := 0; i < vv.Len(); i++ {
- e := vv.Index(i).Interface()
- prefix1 := fmt.Sprintf("%v%v[%v].", prefix, k, i)
- if err := checkUnknownFieldsStruct(e, prefix1, field.Elem()); err != nil {
- return err
- }
- }
- }
- if err := checkUnknownFieldsStruct(v, prefix+k+".", field); err != nil {
- return err
- }
- }
- return nil
-}
-
-func checkUnknownFieldsStruct(val interface{}, prefix string, typ reflect.Type) error {
- if typ.Kind() == reflect.Ptr {
- typ = typ.Elem()
- }
- if typ.Kind() != reflect.Struct {
- return nil
- }
- if typ.PkgPath() == "time" && typ.Name() == "Time" {
- return nil
- }
- inner, err := json.Marshal(val)
- if err != nil {
- return fmt.Errorf("failed to marshal inner struct %q: %v", prefix, err)
- }
- return checkUnknownFieldsRec(inner, prefix, typ)
-}