k8s.io/kubernetes@v1.29.3/test/fuzz/yaml/yaml.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package yaml implements fuzzers for yaml deserialization routines in
    18  // Kubernetes. These targets are compatible with the github.com/dvyukov/go-fuzz
    19  // fuzzing framework.
    20  package yaml
    21  
    22  import (
    23  	"fmt"
    24  	"strings"
    25  
    26  	"gopkg.in/yaml.v2"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	sigyaml "sigs.k8s.io/yaml"
    29  )
    30  
    31  // FuzzDurationStrict is a fuzz target for strict-unmarshaling Duration defined
    32  // in "k8s.io/apimachinery/pkg/apis/meta/v1". This target also checks that the
    33  // unmarshaled result can be marshaled back to the input.
    34  func FuzzDurationStrict(b []byte) int {
    35  	var durationHolder struct {
    36  		D metav1.Duration `json:"d"`
    37  	}
    38  	if err := sigyaml.UnmarshalStrict(b, &durationHolder); err != nil {
    39  		return 0
    40  	}
    41  	result, err := sigyaml.Marshal(&durationHolder)
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  	// Result is in the format "d: <duration>\n", so strip off the trailing
    46  	// newline and convert durationHolder.D to the expected format.
    47  	resultStr := strings.TrimSpace(string(result[:]))
    48  	inputStr := fmt.Sprintf("d: %s", durationHolder.D.Duration)
    49  	if resultStr != inputStr {
    50  		panic(fmt.Sprintf("result(%v) != input(%v)", resultStr, inputStr))
    51  	}
    52  	return 1
    53  }
    54  
    55  // FuzzMicroTimeStrict is a fuzz target for strict-unmarshaling MicroTime
    56  // defined in "k8s.io/apimachinery/pkg/apis/meta/v1". This target also checks
    57  // that the unmarshaled result can be marshaled back to the input.
    58  func FuzzMicroTimeStrict(b []byte) int {
    59  	var microTimeHolder struct {
    60  		T metav1.MicroTime `json:"t"`
    61  	}
    62  	if err := sigyaml.UnmarshalStrict(b, &microTimeHolder); err != nil {
    63  		return 0
    64  	}
    65  	result, err := sigyaml.Marshal(&microTimeHolder)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  	// Result is in the format "t: <time>\n", so strip off the trailing
    70  	// newline and convert microTimeHolder.T to the expected format. If
    71  	// time is zero, the value is marshaled to "null".
    72  	resultStr := strings.TrimSpace(string(result[:]))
    73  	var inputStr string
    74  	if microTimeHolder.T.Time.IsZero() {
    75  		inputStr = "t: null"
    76  	} else {
    77  		inputStr = fmt.Sprintf("t: %s", microTimeHolder.T.Time)
    78  	}
    79  	if resultStr != inputStr {
    80  		panic(fmt.Sprintf("result(%v) != input(%v)", resultStr, inputStr))
    81  	}
    82  	return 1
    83  }
    84  
    85  // FuzzSigYaml is a fuzz target for "sigs.k8s.io/yaml" unmarshaling.
    86  func FuzzSigYaml(b []byte) int {
    87  	t := struct{}{}
    88  	m := map[string]interface{}{}
    89  	var out int
    90  	if err := sigyaml.Unmarshal(b, &m); err == nil {
    91  		out = 1
    92  	}
    93  	if err := sigyaml.Unmarshal(b, &t); err == nil {
    94  		out = 1
    95  	}
    96  	return out
    97  }
    98  
    99  // FuzzTimeStrict is a fuzz target for strict-unmarshaling Time defined in
   100  // "k8s.io/apimachinery/pkg/apis/meta/v1". This target also checks that the
   101  // unmarshaled result can be marshaled back to the input.
   102  func FuzzTimeStrict(b []byte) int {
   103  	var timeHolder struct {
   104  		T metav1.Time `json:"t"`
   105  	}
   106  	if err := sigyaml.UnmarshalStrict(b, &timeHolder); err != nil {
   107  		return 0
   108  	}
   109  	result, err := sigyaml.Marshal(&timeHolder)
   110  	if err != nil {
   111  		panic(err)
   112  	}
   113  	// Result is in the format "t: <time>\n", so strip off the trailing
   114  	// newline and convert timeHolder.T to the expected format. If time is
   115  	// zero, the value is marshaled to "null".
   116  	resultStr := strings.TrimSpace(string(result[:]))
   117  	var inputStr string
   118  	if timeHolder.T.Time.IsZero() {
   119  		inputStr = "t: null"
   120  	} else {
   121  		inputStr = fmt.Sprintf("t: %s", timeHolder.T.Time)
   122  	}
   123  	if resultStr != inputStr {
   124  		panic(fmt.Sprintf("result(%v) != input(%v)", resultStr, inputStr))
   125  	}
   126  	return 1
   127  }
   128  
   129  // FuzzYamlV2 is a fuzz target for "gopkg.in/yaml.v2" unmarshaling.
   130  func FuzzYamlV2(b []byte) int {
   131  	t := struct{}{}
   132  	m := map[string]interface{}{}
   133  	var out int
   134  	if err := yaml.Unmarshal(b, &m); err == nil {
   135  		out = 1
   136  	}
   137  	if err := yaml.Unmarshal(b, &t); err == nil {
   138  		out = 1
   139  	}
   140  	return out
   141  }