github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/syz-cluster/pkg/triage/fuzz_target.go (about) 1 // Copyright 2025 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package triage 5 6 import ( 7 "sort" 8 "strings" 9 10 "github.com/google/syzkaller/syz-cluster/pkg/api" 11 ) 12 13 func SelectFuzzConfigs(series *api.Series, fuzzConfigs []*api.FuzzTriageTarget) []*api.KernelFuzzConfig { 14 seriesCc := map[string]bool{} 15 for _, cc := range series.Cc { 16 seriesCc[strings.ToLower(cc)] = true 17 } 18 var ret, defaultRet []*api.KernelFuzzConfig 19 for _, config := range fuzzConfigs { 20 intersects := false 21 for _, cc := range config.EmailLists { 22 intersects = intersects || seriesCc[cc] 23 } 24 if intersects { 25 ret = append(ret, config.Campaigns...) 26 } else if len(config.EmailLists) == 0 { 27 defaultRet = append(defaultRet, config.Campaigns...) 28 } 29 } 30 // We want to return the fallback option only if no element matched exactly. 31 if len(ret) > 0 { 32 return ret 33 } 34 return defaultRet 35 } 36 37 type MergedFuzzConfig struct { 38 KernelConfig string 39 FuzzConfig *api.FuzzConfig 40 } 41 42 func MergeKernelFuzzConfigs(configs []*api.KernelFuzzConfig) []*MergedFuzzConfig { 43 type groupKey struct { 44 config string 45 track string 46 bugTitleRe string 47 } 48 groups := map[groupKey][]*api.KernelFuzzConfig{} 49 var orderedKeys []groupKey 50 for _, config := range configs { 51 // Some of the different fuzz configs may still be merged together, 52 // e.g. if they only differ in the syscall lists and corpuses. 53 key := groupKey{config.KernelConfig, config.Track, config.BugTitleRe} 54 if _, ok := groups[key]; !ok { 55 orderedKeys = append(orderedKeys, key) 56 } 57 groups[key] = append(groups[key], config) 58 } 59 var ret []*MergedFuzzConfig 60 for _, key := range orderedKeys { 61 // TODO: is there way to auto-generate a prefix? 62 ret = append(ret, &MergedFuzzConfig{ 63 KernelConfig: key.config, 64 FuzzConfig: mergeFuzzConfigs(groups[key]), 65 }) 66 } 67 return ret 68 } 69 70 func mergeFuzzConfigs(configs []*api.KernelFuzzConfig) *api.FuzzConfig { 71 var ret api.FuzzConfig 72 for _, config := range configs { 73 if config.Focus != "" { 74 ret.Focus = append(ret.Focus, config.Focus) 75 } 76 if config.CorpusURL != "" { 77 ret.CorpusURLs = append(ret.CorpusURLs, config.CorpusURL) 78 } 79 ret.SkipCoverCheck = ret.SkipCoverCheck || config.SkipCoverCheck 80 // Must be the same. 81 ret.BugTitleRe = config.BugTitleRe 82 ret.Track = config.Track 83 } 84 ret.Focus = unique(ret.Focus) 85 ret.CorpusURLs = unique(ret.CorpusURLs) 86 return &ret 87 } 88 89 func unique(list []string) []string { 90 seen := make(map[string]struct{}, len(list)) 91 for _, s := range list { 92 seen[s] = struct{}{} 93 } 94 var unique []string 95 for s := range seen { 96 unique = append(unique, s) 97 } 98 sort.Strings(unique) 99 return unique 100 }