diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-06-01 11:17:54 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-06-01 11:17:54 +0200 |
| commit | 84eb5fd389bc4ae247048d1f20ec9577935f4f04 (patch) | |
| tree | b7ff3a69478dc0965788e84e5c5ddbb35a9f3e01 | |
| parent | 2cf166ec847e808c72cc8942d696d7c66e78acff (diff) | |
config: split and refactor
Introduce generic config.Load function that can be
reused across multiple programs (syz-manager, syz-gce, etc).
Move the generic config functionality to pkg/config package.
The idea is to move all helper (non-main) packages to pkg/ dir,
because we have more and more of them and they pollute the top dir.
Move the syz-manager config parts into syz-manager/config package.
| -rw-r--r-- | config/config_test.go | 24 | ||||
| -rw-r--r-- | pkg/config/config.go | 61 | ||||
| -rw-r--r-- | pkg/config/config_test.go | 65 | ||||
| -rw-r--r-- | repro/repro.go | 2 | ||||
| -rw-r--r-- | syz-gce/syz-gce.go | 26 | ||||
| -rw-r--r-- | syz-manager/config/config.go (renamed from config/config.go) | 50 | ||||
| -rw-r--r-- | syz-manager/manager.go | 2 | ||||
| -rw-r--r-- | tools/syz-crush/crush.go | 2 | ||||
| -rw-r--r-- | tools/syz-repro/repro.go | 2 |
9 files changed, 144 insertions, 90 deletions
diff --git a/config/config_test.go b/config/config_test.go deleted file mode 100644 index 67bcd5059..000000000 --- a/config/config_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -package config - -import ( - "testing" -) - -func TestUnknown(t *testing.T) { - data := `{"foo": "bar"}` - _, _, err := parse([]byte(data)) - if err == nil || err.Error() != "unknown field 'foo' in config" { - t.Fatalf("unknown field is not detected (%v)", err) - } -} - -func TestReflectUnknown(t *testing.T) { - data := `{"http": "localhost:56741","ParsedIgnores": [], "Odroid_Hub_Bus": "bus"}` - _, _, err := parse([]byte(data)) - if err == nil || err.Error() != "unknown field 'ParsedIgnores' in config" { - t.Fatalf("unknown field is not detected (%v)", err) - } -} diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 000000000..feb031c71 --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,61 @@ +// Copyright 2017 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package config + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "reflect" + "strings" +) + +func Load(filename string, cfg interface{}) error { + if filename == "" { + return fmt.Errorf("no config file specified") + } + data, err := ioutil.ReadFile(filename) + if err != nil { + return fmt.Errorf("failed to read config file: %v", err) + } + return load(data, cfg) +} + +func load(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 { + return fmt.Errorf("failed to parse config file: %v", err) + } + return nil +} + +func checkUnknownFields(data []byte, typ reflect.Type) error { + if typ.Kind() != reflect.Ptr { + return fmt.Errorf("config type is not pointer to struct") + } + typ = typ.Elem() + if typ.Kind() != reflect.Struct { + return fmt.Errorf("config type is not pointer to struct") + } + fields := make(map[string]bool) + for i := 0; i < typ.NumField(); i++ { + field := typ.Field(i) + if field.Tag.Get("json") == "-" { + continue + } + fields[strings.ToLower(field.Name)] = true + } + 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 := range f { + if !fields[strings.ToLower(k)] { + return fmt.Errorf("unknown field '%v' in config", k) + } + } + return nil +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 000000000..73ad3502c --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,65 @@ +// Copyright 2016 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package config + +import ( + "fmt" + "reflect" + "testing" +) + +func TestUnknown(t *testing.T) { + type Config struct { + Foo int + Bar string + Baz string `json:"-"` + } + tests := []struct { + input string + output Config + err string + }{ + { + `{"foo": 42}`, + Config{ + Foo: 42, + }, + "", + }, + { + `{"BAR": "Baz", "foo": 42}`, + Config{ + Foo: 42, + Bar: "Baz", + }, + "", + }, + { + `{"foobar": 42}`, + Config{}, + "unknown field 'foobar' in config", + }, + { + `{"foo": 1, "baz": "baz", "bar": "bar"}`, + Config{}, + "unknown field 'baz' in config", + }, + } + for i, test := range tests { + t.Run(fmt.Sprint(i), func(t *testing.T) { + var cfg Config + err := load([]byte(test.input), &cfg) + errStr := "" + if err != nil { + errStr = err.Error() + } + if test.err != errStr { + t.Fatalf("bad err: want '%v', got '%v'", test.err, errStr) + } + if !reflect.DeepEqual(test.output, cfg) { + t.Fatalf("bad output: want '%#v', got '%#v'", test.output, cfg) + } + }) + } +} diff --git a/repro/repro.go b/repro/repro.go index b9124942e..1d7f39518 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -11,12 +11,12 @@ import ( "sync" "time" - "github.com/google/syzkaller/config" "github.com/google/syzkaller/csource" "github.com/google/syzkaller/fileutil" . "github.com/google/syzkaller/log" "github.com/google/syzkaller/prog" "github.com/google/syzkaller/report" + "github.com/google/syzkaller/syz-manager/config" "github.com/google/syzkaller/vm" ) diff --git a/syz-gce/syz-gce.go b/syz-gce/syz-gce.go index 2e254556c..9bdedbe5b 100644 --- a/syz-gce/syz-gce.go +++ b/syz-gce/syz-gce.go @@ -38,10 +38,11 @@ import ( "time" "cloud.google.com/go/storage" - "github.com/google/syzkaller/config" "github.com/google/syzkaller/dashboard" "github.com/google/syzkaller/gce" . "github.com/google/syzkaller/log" + pkgconfig "github.com/google/syzkaller/pkg/config" + "github.com/google/syzkaller/syz-manager/config" "golang.org/x/net/context" ) @@ -89,7 +90,12 @@ type Action interface { func main() { flag.Parse() - cfg = readConfig(*flagConfig) + cfg = &Config{ + Use_Dashboard_Patches: true, + } + if err := pkgconfig.Load(*flagConfig, cfg); err != nil { + Fatalf("failed to load config file: %v", err) + } EnableLogCaching(1000, 1<<20) initHttp(fmt.Sprintf(":%v", cfg.Http_Port)) @@ -493,22 +499,6 @@ func (a *GCSImageAction) Build() error { return nil } -func readConfig(filename string) *Config { - if filename == "" { - Fatalf("supply config in -config flag") - } - data, err := ioutil.ReadFile(filename) - if err != nil { - Fatalf("failed to read config file: %v", err) - } - cfg := new(Config) - cfg.Use_Dashboard_Patches = true - if err := json.Unmarshal(data, cfg); err != nil { - Fatalf("failed to parse config file: %v", err) - } - return cfg -} - func writeManagerConfig(cfg *Config, httpPort int, file string) error { tag, err := ioutil.ReadFile("image/tag") if err != nil { diff --git a/config/config.go b/syz-manager/config/config.go index 99314249b..12db5696d 100644 --- a/config/config.go +++ b/syz-manager/config/config.go @@ -4,16 +4,14 @@ package config import ( - "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" - "reflect" "regexp" "strings" "github.com/google/syzkaller/fileutil" + pkgconfig "github.com/google/syzkaller/pkg/config" "github.com/google/syzkaller/sys" "github.com/google/syzkaller/vm" ) @@ -79,28 +77,14 @@ type Config struct { } func Parse(filename string) (*Config, map[int]bool, error) { - if filename == "" { - return nil, nil, fmt.Errorf("supply config in -config flag") + cfg := &Config{ + Cover: true, + Reproduce: true, + Sandbox: "setuid", } - data, err := ioutil.ReadFile(filename) - if err != nil { - return nil, nil, fmt.Errorf("failed to read config file: %v", err) - } - return parse(data) -} - -func parse(data []byte) (*Config, map[int]bool, error) { - err := checkUnknownFields(data) - if err != nil { + if err := pkgconfig.Load(filename, cfg); err != nil { return nil, nil, err } - cfg := new(Config) - cfg.Cover = true - cfg.Reproduce = true - cfg.Sandbox = "setuid" - if err := json.Unmarshal(data, cfg); err != nil { - return nil, nil, fmt.Errorf("failed to parse config file: %v", err) - } if _, err := os.Stat(filepath.Join(cfg.Syzkaller, "bin/syz-fuzzer")); err != nil { return nil, nil, fmt.Errorf("bad config syzkaller param: can't find bin/syz-fuzzer") } @@ -362,25 +346,3 @@ func CreateVMConfig(cfg *Config, index int) (*vm.Config, error) { } return vmCfg, nil } - -func checkUnknownFields(data []byte) error { - structType := reflect.ValueOf(Config{}).Type() - fields := make(map[string]bool) - for i := 0; i < structType.NumField(); i++ { - field := structType.Field(i) - if field.Tag.Get("json") == "-" { - continue - } - fields[strings.ToLower(field.Name)] = true - } - 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 := range f { - if !fields[strings.ToLower(k)] { - return fmt.Errorf("unknown field '%v' in config", k) - } - } - return nil -} diff --git a/syz-manager/manager.go b/syz-manager/manager.go index ad24f4c39..0cdfa320d 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -19,7 +19,6 @@ import ( "syscall" "time" - "github.com/google/syzkaller/config" "github.com/google/syzkaller/cover" "github.com/google/syzkaller/csource" "github.com/google/syzkaller/dashboard" @@ -30,6 +29,7 @@ import ( "github.com/google/syzkaller/report" "github.com/google/syzkaller/repro" . "github.com/google/syzkaller/rpctype" + "github.com/google/syzkaller/syz-manager/config" "github.com/google/syzkaller/vm" _ "github.com/google/syzkaller/vm/adb" _ "github.com/google/syzkaller/vm/gce" diff --git a/tools/syz-crush/crush.go b/tools/syz-crush/crush.go index d519107f9..f1796baf0 100644 --- a/tools/syz-crush/crush.go +++ b/tools/syz-crush/crush.go @@ -18,8 +18,8 @@ import ( "syscall" "time" - "github.com/google/syzkaller/config" . "github.com/google/syzkaller/log" + "github.com/google/syzkaller/syz-manager/config" "github.com/google/syzkaller/vm" _ "github.com/google/syzkaller/vm/adb" _ "github.com/google/syzkaller/vm/gce" diff --git a/tools/syz-repro/repro.go b/tools/syz-repro/repro.go index 841a121d1..064846991 100644 --- a/tools/syz-repro/repro.go +++ b/tools/syz-repro/repro.go @@ -11,10 +11,10 @@ import ( "os/signal" "syscall" - "github.com/google/syzkaller/config" "github.com/google/syzkaller/csource" . "github.com/google/syzkaller/log" "github.com/google/syzkaller/repro" + "github.com/google/syzkaller/syz-manager/config" "github.com/google/syzkaller/vm" _ "github.com/google/syzkaller/vm/adb" _ "github.com/google/syzkaller/vm/gce" |
