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, µTimeHolder); err != nil { 63 return 0 64 } 65 result, err := sigyaml.Marshal(µTimeHolder) 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 }