diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2021-11-17 12:36:48 +0000 |
|---|---|---|
| committer | Aleksandr Nogikh <wp32pw@gmail.com> | 2021-11-19 19:06:55 +0100 |
| commit | 780b27623e2c0284dfb0c8e0392463d1eef00e92 (patch) | |
| tree | c8dcefe94021fc3e0a5693e082a9c3751c64997f /pkg/config/merge.go | |
| parent | 3a9d0024ba818c5b37058d9ac6fdfc0ddfa78be6 (diff) | |
tools/syz-testbed: support per-checkout syz-manager configs
Let the user of the tool specify individual syz-manager configs for
checkouts. A base config is specified as previously and then individual
parts of jsons are applied to that base config, e.g.
<...>
"checkouts": [
{
"name": "first",
"repo": "https://github.com/google/syzkaller.git",
},
{
"name": "second",
"repo": "https://github.com/google/syzkaller.git",
"manager_config": {
"kernel_obj": "/tmp/linux-stable2"
}
}
],
"manager_config": {
"target": "linux/amd64",
"kernel_obj": "/tmp/linux-stable",
<...>
}
<...>
Diffstat (limited to 'pkg/config/merge.go')
| -rw-r--r-- | pkg/config/merge.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/pkg/config/merge.go b/pkg/config/merge.go new file mode 100644 index 000000000..49a7254de --- /dev/null +++ b/pkg/config/merge.go @@ -0,0 +1,57 @@ +// Copyright 2021 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" +) + +// Unfortunately, if we want to apply a JSON patch to some configuration, we cannot just unmarshal +// it twice - in that case json.RawMessage objects will be completely replaced, but not merged. +func MergeJSONData(left, right []byte) ([]byte, error) { + vLeft, err := parseFragment(left) + if err != nil { + return nil, err + } + vRight, err := parseFragment(right) + if err != nil { + return nil, err + } + merged := mergeRecursive(vLeft, vRight) + return json.Marshal(merged) +} + +func parseFragment(input []byte) (parsed interface{}, err error) { + if len(input) == 0 { + // For convenience, we allow empty strings to be passed to the function that merges JSONs. + return + } + err = json.Unmarshal(json.RawMessage(input), &parsed) + return +} + +// If one of the elements is not a map, use the new one. +// Otherwise, recursively merge map elements. +func mergeRecursive(left, right interface{}) interface{} { + if left == nil { + return right + } + if right == nil { + return left + } + mLeft, okLeft := left.(map[string]interface{}) + mRight, okRight := right.(map[string]interface{}) + if !okLeft || !okRight { + return right + } + for key, val := range mRight { + valLeft, ok := mLeft[key] + if ok { + mLeft[key] = mergeRecursive(valLeft, val) + } else { + mLeft[key] = val + } + } + return mLeft +} |
