aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-06-01 11:17:54 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-06-01 11:17:54 +0200
commit84eb5fd389bc4ae247048d1f20ec9577935f4f04 (patch)
treeb7ff3a69478dc0965788e84e5c5ddbb35a9f3e01
parent2cf166ec847e808c72cc8942d696d7c66e78acff (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.go24
-rw-r--r--pkg/config/config.go61
-rw-r--r--pkg/config/config_test.go65
-rw-r--r--repro/repro.go2
-rw-r--r--syz-gce/syz-gce.go26
-rw-r--r--syz-manager/config/config.go (renamed from config/config.go)50
-rw-r--r--syz-manager/manager.go2
-rw-r--r--tools/syz-crush/crush.go2
-rw-r--r--tools/syz-repro/repro.go2
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"