istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/fuzz/analyzer_fuzzer.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fuzz 16 17 import ( 18 "bytes" 19 "os" 20 21 fuzz "github.com/AdaLogics/go-fuzz-headers" 22 23 "istio.io/istio/pkg/config" 24 "istio.io/istio/pkg/config/analysis" 25 "istio.io/istio/pkg/config/analysis/analyzers" 26 "istio.io/istio/pkg/config/analysis/local" 27 "istio.io/istio/pkg/config/analysis/scope" 28 "istio.io/istio/pkg/log" 29 ) 30 31 var availableAnalyzers = analyzers.All() 32 33 // createRandomConfigFile creates a single fuzzed config file 34 func createRandomConfigFile(f *fuzz.ConsumeFuzzer) (string, error) { 35 data, err := f.GetBytes() 36 if err != nil { 37 return "nobytes", err 38 } 39 tmpfile, err := os.CreateTemp("", "example") 40 if err != nil { 41 return "nofile", err 42 } 43 if _, err := tmpfile.Write(data); err != nil { 44 return "nofile", err 45 } 46 if err := tmpfile.Close(); err != nil { 47 return "nofile", err 48 } 49 return tmpfile.Name(), nil 50 } 51 52 // createRandomConfigFiles creates a slice of ReaderSources 53 func createRandomConfigFiles(f *fuzz.ConsumeFuzzer) ([]local.ReaderSource, error) { 54 var files []local.ReaderSource 55 56 numberOfFiles, err := f.GetInt() 57 if err != nil { 58 return files, err 59 } 60 maxFiles := numberOfFiles % 10 61 62 // Gather test files 63 for i := 0; i < maxFiles; i++ { 64 name, err := f.GetString() 65 if err != nil { 66 return files, err 67 } 68 rBytes, err := f.GetBytes() 69 if err != nil { 70 return files, err 71 } 72 r := bytes.NewReader(rBytes) 73 files = append(files, local.ReaderSource{Name: name, Reader: r}) 74 } 75 return files, nil 76 } 77 78 // runAnalyzer runs the analyzer 79 func runAnalyzer(sa *local.IstiodAnalyzer) (local.AnalysisResult, error) { 80 prevLogLevel := scope.Processing.GetOutputLevel() 81 scope.Processing.SetOutputLevel(log.NoneLevel) 82 defer scope.Processing.SetOutputLevel(prevLogLevel) 83 84 cancel := make(chan struct{}) 85 result, err := sa.Analyze(cancel) 86 if err != nil { 87 return local.AnalysisResult{}, err 88 } 89 return result, err 90 } 91 92 // FuzzAnalyzer implements the fuzzer 93 func FuzzAnalyzer(data []byte) int { 94 f := fuzz.NewConsumer(data) 95 analyzerIndex, err := f.GetInt() 96 if err != nil { 97 return 0 98 } 99 analyzer := availableAnalyzers[analyzerIndex%len(availableAnalyzers)] 100 101 requestedInputsByAnalyzer := make(map[string]map[config.GroupVersionKind]struct{}) 102 analyzerName := analyzer.Metadata().Name 103 cr := func(col config.GroupVersionKind) { 104 if _, ok := requestedInputsByAnalyzer[analyzerName]; !ok { 105 requestedInputsByAnalyzer[analyzerName] = make(map[config.GroupVersionKind]struct{}) 106 } 107 requestedInputsByAnalyzer[analyzerName][col] = struct{}{} 108 } 109 110 // Mesh config file 111 addMeshConfig, err := f.GetBool() 112 if err != nil { 113 return 0 114 } 115 meshConfigFile := "" 116 if addMeshConfig { 117 meshConfigFile, err = createRandomConfigFile(f) 118 if err != nil { 119 return 0 120 } 121 defer os.Remove(meshConfigFile) 122 } 123 124 // Mesh networks file 125 addMeshNetworks, err := f.GetBool() 126 if err != nil { 127 return 0 128 } 129 meshNetworkFile := "" 130 if addMeshNetworks { 131 meshNetworkFile, err = createRandomConfigFile(f) 132 if err != nil { 133 return 0 134 } 135 defer os.Remove(meshNetworkFile) 136 } 137 138 configFiles, err := createRandomConfigFiles(f) 139 if err != nil { 140 return 0 141 } 142 143 sa := local.NewSourceAnalyzer(analysis.Combine("testCase", analyzer), "", "istio-system", cr) 144 if addMeshConfig { 145 err = sa.AddFileKubeMeshConfig(meshConfigFile) 146 if err != nil { 147 return 0 148 } 149 } 150 if addMeshNetworks { 151 err = sa.AddFileKubeMeshNetworks(meshNetworkFile) 152 if err != nil { 153 return 0 154 } 155 } 156 157 // Include default resources 158 err = sa.AddDefaultResources() 159 if err != nil { 160 return 0 161 } 162 163 // Include resources from test files 164 err = sa.AddReaderKubeSource(configFiles) 165 if err != nil { 166 return 0 167 } 168 _, _ = runAnalyzer(sa) 169 return 1 170 }