// Copyright 2015 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. // Only build when go-fuzz is in use // +build gofuzz package promql import ( "io" "github.com/prometheus/prometheus/pkg/textparse" ) // PromQL parser fuzzing instrumentation for use with // https://github.com/dvyukov/go-fuzz. // // Fuzz each parser by building appropriately instrumented parser, ex. // FuzzParseMetric and execute it with it's // // go-fuzz-build -func FuzzParseMetric -o FuzzParseMetric.zip github.com/prometheus/prometheus/promql // // And then run the tests with the appropriate inputs // // go-fuzz -bin FuzzParseMetric.zip -workdir fuzz-data/parser.ParseMetric // // Further input samples should go in the folders fuzz-data/parser.ParseMetric/corpus. // // Repeat for FuzzParseOpenMetric, FuzzParseMetricSelector and FuzzParseExpr. // Tuning which value is returned from Fuzz*-functions has a strong influence // on how quick the fuzzer converges on "interesting" cases. At least try // switching between fuzzMeh (= included in corpus, but not a priority) and // fuzzDiscard (=don't use this input for re-building later inputs) when // experimenting. const ( fuzzInteresting = 1 fuzzMeh = 0 fuzzDiscard = -1 ) func fuzzParseMetricWithContentType(in []byte, contentType string) int { p := textparse.New(in, contentType) var err error for { _, err = p.Next() if err != nil { break } } if err == io.EOF { err = nil } if err == nil { return fuzzInteresting } return fuzzMeh } // Fuzz the metric parser. // // Note that this is not the parser for the text-based exposition-format; that // lives in github.com/prometheus/client_golang/text. func FuzzParseMetric(in []byte) int { return fuzzParseMetricWithContentType(in, "") } func FuzzParseOpenMetric(in []byte) int { return fuzzParseMetricWithContentType(in, "application/openmetrics-text") } // Fuzz the metric selector parser. func FuzzParseMetricSelector(in []byte) int { _, err := parser.ParseMetricSelector(string(in)) if err == nil { return fuzzInteresting } return fuzzMeh } // Fuzz the expression parser. func FuzzParseExpr(in []byte) int { _, err := parser.ParseExpr(string(in)) if err == nil { return fuzzInteresting } return fuzzMeh }