github.com/segmentio/encoding@v0.4.0/json/fuzz/fuzz.go (about) 1 // +build ignore 2 3 // Copyright 2015 go-fuzz project authors. All rights reserved. 4 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 5 6 package fuzz 7 8 import ( 9 "bytes" 10 encodingJSON "encoding/json" 11 "fmt" 12 "reflect" 13 14 "github.com/dvyukov/go-fuzz-corpus/fuzz" 15 "github.com/segmentio/encoding/json" 16 ) 17 18 func fixS(v interface{}) { 19 if s, ok := v.(*S); ok { 20 if len(s.P) == 0 { 21 s.P = []byte(`""`) 22 } 23 } 24 } 25 26 func Fuzz(data []byte) int { 27 score := 0 28 for _, ctor := range []func() interface{}{ 29 func() interface{} { return nil }, 30 func() interface{} { return new([]interface{}) }, 31 func() interface{} { m := map[string]string{}; return &m }, 32 func() interface{} { m := map[string]interface{}{}; return &m }, 33 func() interface{} { return new(S) }, 34 } { 35 // Note: we modified the test to verify that we behavior like the 36 // standard encoding/json package, whether it's right or wrong. 37 v1 := ctor() 38 v2 := ctor() 39 40 err1 := encodingJSON.Unmarshal(data, v1) 41 err2 := json.Unmarshal(data, v2) 42 43 if err1 != nil { 44 if err2 != nil { 45 // both implementations report an error 46 if reflect.TypeOf(err1) != reflect.TypeOf(err2) { 47 fmt.Printf("input: %s\n", string(data)) 48 fmt.Printf("encoding/json.Unmarshal(%T): %T: %s\n", v1, err1, err1) 49 fmt.Printf("segmentio/encoding/json.Unmarshal(%T): %T: %s\n", v2, err2, err2) 50 panic("error types mismatch") 51 } 52 continue 53 } else { 54 fmt.Printf("input: %s\n", string(data)) 55 fmt.Printf("encoding/json.Unmarshal(%T): %T: %s\n", v1, err1, err1) 56 fmt.Printf("segmentio/encoding/json.Unmarshal(%T): <nil>\n") 57 panic("error values mismatch") 58 } 59 } else { 60 if err2 != nil { 61 fmt.Printf("input: %s\n", string(data)) 62 fmt.Printf("encoding/json.Unmarshal(%T): <nil>\n") 63 fmt.Printf("segmentio/encoding/json.Unmarshal(%T): %T: %s\n", v2, err2, err2) 64 panic("error values mismatch") 65 } else { 66 // both implementations pass 67 } 68 } 69 70 score = 1 71 fixS(v1) 72 fixS(v2) 73 if !fuzz.DeepEqual(v1, v2) { 74 fmt.Printf("input: %s\n", string(data)) 75 fmt.Printf("encoding/json: %#v\n", v1) 76 fmt.Printf("segmentio/encoding: %#v\n", v2) 77 panic("not equal") 78 } 79 80 data1, err := encodingJSON.Marshal(v1) 81 if err != nil { 82 panic(err) 83 } 84 data2, err := json.Marshal(v2) 85 if err != nil { 86 panic(err) 87 } 88 if !bytes.Equal(data1, data2) { 89 fmt.Printf("input: %s\n", string(data)) 90 fmt.Printf("encoding/json: %s\n", string(data1)) 91 fmt.Printf("segmentio/encoding: %s\n", string(data2)) 92 panic("not equal") 93 } 94 } 95 return score 96 } 97 98 type S struct { 99 A int `json:",omitempty"` 100 B string `json:"B1,omitempty"` 101 C float64 102 D bool 103 E uint8 104 F []byte 105 G interface{} 106 H map[string]interface{} 107 I map[string]string 108 J []interface{} 109 K []string 110 L S1 111 M *S1 112 N *int 113 O **int 114 P json.RawMessage 115 Q Marshaller 116 R int `json:"-"` 117 S int `json:",string"` 118 } 119 120 type S1 struct { 121 A int 122 B string 123 } 124 125 type Marshaller struct { 126 v string 127 } 128 129 func (m *Marshaller) MarshalJSON() ([]byte, error) { 130 return json.Marshal(m.v) 131 } 132 133 func (m *Marshaller) UnmarshalJSON(data []byte) error { 134 return json.Unmarshal(data, &m.v) 135 }