prometheus/util/fuzzing/corpus_gen/main.go
Julien Pivotto de0a864b5c Fuzzing: Move to go fuzzing
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-01-12 12:59:10 +01:00

116 lines
3.9 KiB
Go

// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build fuzzing
//go:generate go run -tags fuzzing .
package main
import (
"archive/zip"
"fmt"
"os"
"path/filepath"
"sort"
"github.com/prometheus/prometheus/util/fuzzing"
)
func main() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
fmt.Println("Successfully generated all seed corpus ZIP files.")
}
func run() error {
// Generate FuzzParseExpr seed corpus.
exprs, err := fuzzing.GetCorpusForFuzzParseExpr()
if err != nil {
return fmt.Errorf("failed to get corpus for FuzzParseExpr: %w", err)
}
if err := generateZipFromStrings("fuzzParseExpr", exprs); err != nil {
return fmt.Errorf("failed to generate FuzzParseExpr_seed_corpus.zip: %w", err)
}
fmt.Printf("Generated fuzzParseExpr_seed_corpus.zip with %d entries.\n", len(exprs))
// Generate FuzzParseMetricSelector seed corpus.
selectors := fuzzing.GetCorpusForFuzzParseMetricSelector()
if err := generateZipFromStrings("fuzzParseMetricSelector", selectors); err != nil {
return fmt.Errorf("failed to generate FuzzParseMetricSelector_seed_corpus.zip: %w", err)
}
fmt.Printf("Generated fuzzParseMetricSelector_seed_corpus.zip with %d entries.\n", len(selectors))
// Generate FuzzParseMetricText seed corpus.
metrics := fuzzing.GetCorpusForFuzzParseMetricText()
if err := generateZipFromBytes("fuzzParseMetricText", metrics); err != nil {
return fmt.Errorf("failed to generate FuzzParseMetricText_seed_corpus.zip: %w", err)
}
fmt.Printf("Generated fuzzParseMetricText_seed_corpus.zip with %d entries.\n", len(metrics))
// Generate FuzzParseOpenMetric seed corpus.
openMetrics := fuzzing.GetCorpusForFuzzParseOpenMetric()
if err := generateZipFromBytes("fuzzParseOpenMetric", openMetrics); err != nil {
return fmt.Errorf("failed to generate FuzzParseOpenMetric_seed_corpus.zip: %w", err)
}
fmt.Printf("Generated fuzzParseOpenMetric_seed_corpus.zip with %d entries.\n", len(openMetrics))
return nil
}
// generateZipFromBytes creates a seed corpus ZIP file from a slice of byte slices.
func generateZipFromBytes(fuzzName string, corpus [][]byte) error {
// Sort corpus deterministically.
sorted := make([][]byte, len(corpus))
copy(sorted, corpus)
sort.Slice(sorted, func(i, j int) bool {
return string(sorted[i]) < string(sorted[j])
})
// Create ZIP file in parent directory.
zipPath := filepath.Join("..", fuzzName+"_seed_corpus.zip")
zipFile, err := os.Create(zipPath)
if err != nil {
return fmt.Errorf("failed to create zip file: %w", err)
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
// Add each corpus entry as a file.
for i, entry := range sorted {
fileName := fmt.Sprintf("expr%d", i)
writer, err := zipWriter.Create(fileName)
if err != nil {
return fmt.Errorf("failed to create zip entry %s: %w", fileName, err)
}
if _, err := writer.Write(entry); err != nil {
return fmt.Errorf("failed to write zip entry %s: %w", fileName, err)
}
}
return nil
}
// generateZipFromStrings creates a seed corpus ZIP file from a slice of strings.
func generateZipFromStrings(fuzzName string, corpus []string) error {
// Convert []string to [][]byte and delegate to generateZipFromBytes
byteCorpus := make([][]byte, len(corpus))
for i, s := range corpus {
byteCorpus[i] = []byte(s)
}
return generateZipFromBytes(fuzzName, byteCorpus)
}