1
2
3
4
5 package json
6
7 import (
8 "bytes"
9 "errors"
10 "io"
11 "math/rand"
12 "reflect"
13 "testing"
14 )
15
16 func FuzzCoder(f *testing.F) {
17
18 for _, td := range coderTestdata {
19 f.Add(int64(0), []byte(td.in))
20 }
21 for _, td := range decoderErrorTestdata {
22 f.Add(int64(0), []byte(td.in))
23 }
24 for _, td := range encoderErrorTestdata {
25 f.Add(int64(0), []byte(td.wantOut))
26 }
27 for _, td := range jsonTestdata() {
28 f.Add(int64(0), td.data)
29 }
30
31 f.Fuzz(func(t *testing.T, seed int64, b []byte) {
32 var tokVals []tokOrVal
33 rn := rand.NewSource(seed)
34
35
36
37 src := bytes.NewReader(b)
38 dec := NewDecoder(src)
39 for {
40 if rn.Int63()%8 > 0 {
41 tok, err := dec.ReadToken()
42 if err != nil {
43 if err == io.EOF {
44 break
45 }
46 t.Skipf("Decoder.ReadToken error: %v", err)
47 }
48 tokVals = append(tokVals, tok.Clone())
49 } else {
50 val, err := dec.ReadValue()
51 if err != nil {
52 expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']'
53 if expectError && errors.As(err, new(*SyntacticError)) {
54 continue
55 }
56 if err == io.EOF {
57 break
58 }
59 t.Skipf("Decoder.ReadValue error: %v", err)
60 }
61 tokVals = append(tokVals, append(zeroValue, val...))
62 }
63 }
64
65
66
67 dst := new(bytes.Buffer)
68 enc := NewEncoder(dst)
69 for _, tokVal := range tokVals {
70 switch tokVal := tokVal.(type) {
71 case Token:
72 if err := enc.WriteToken(tokVal); err != nil {
73 t.Fatalf("Encoder.WriteToken error: %v", err)
74 }
75 case RawValue:
76 if err := enc.WriteValue(tokVal); err != nil {
77 t.Fatalf("Encoder.WriteValue error: %v", err)
78 }
79 }
80 }
81
82
83 var got, want []Token
84 for dec := NewDecoder(bytes.NewReader(b)); dec.PeekKind() > 0; {
85 tok, err := dec.ReadToken()
86 if err != nil {
87 t.Fatalf("Decoder.ReadToken error: %v", err)
88 }
89 got = append(got, tok.Clone())
90 }
91 for dec := NewDecoder(dst); dec.PeekKind() > 0; {
92 tok, err := dec.ReadToken()
93 if err != nil {
94 t.Fatalf("Decoder.ReadToken error: %v", err)
95 }
96 want = append(want, tok.Clone())
97 }
98 if !equalTokens(got, want) {
99 t.Fatalf("mismatching output:\ngot %v\nwant %v", got, want)
100 }
101 })
102 }
103
104 func FuzzResumableDecoder(f *testing.F) {
105 for _, td := range resumableDecoderTestdata {
106 f.Add(int64(0), []byte(td))
107 }
108
109 f.Fuzz(func(t *testing.T, seed int64, b []byte) {
110 rn := rand.NewSource(seed)
111
112
113
114 t.Run("ReadToken", func(t *testing.T) {
115 decGot := NewDecoder(&FaultyBuffer{B: b, MaxBytes: 8, Rand: rn})
116 decWant := NewDecoder(bytes.NewReader(b))
117 gotTok, gotErr := decGot.ReadToken()
118 wantTok, wantErr := decWant.ReadToken()
119 if gotTok.String() != wantTok.String() || !reflect.DeepEqual(gotErr, wantErr) {
120 t.Errorf("Decoder.ReadToken = (%v, %v), want (%v, %v)", gotTok, gotErr, wantTok, wantErr)
121 }
122 })
123 t.Run("ReadValue", func(t *testing.T) {
124 decGot := NewDecoder(&FaultyBuffer{B: b, MaxBytes: 8, Rand: rn})
125 decWant := NewDecoder(bytes.NewReader(b))
126 gotVal, gotErr := decGot.ReadValue()
127 wantVal, wantErr := decWant.ReadValue()
128 if !reflect.DeepEqual(gotVal, wantVal) || !reflect.DeepEqual(gotErr, wantErr) {
129 t.Errorf("Decoder.ReadValue = (%s, %v), want (%s, %v)", gotVal, gotErr, wantVal, wantErr)
130 }
131 })
132 })
133 }
134
135 func FuzzRawValueReformat(f *testing.F) {
136 for _, td := range rawValueTestdata {
137 f.Add([]byte(td.in))
138 }
139
140
141 isValid := func(opts DecodeOptions, b []byte) bool {
142 d := opts.NewDecoder(bytes.NewReader(b))
143 _, errVal := d.ReadValue()
144 _, errEOF := d.ReadToken()
145 return errVal == nil && errEOF == io.EOF
146 }
147
148
149 stripWhitespace := func(in []byte) (out []byte) {
150 out = make([]byte, 0, len(in))
151 for _, c := range in {
152 switch c {
153 case ' ', '\n', '\r', '\t':
154 default:
155 out = append(out, c)
156 }
157 }
158 return out
159 }
160
161
162 unmarshal := func(in []byte) (out any) {
163 if err := Unmarshal(in, &out); err != nil {
164 return nil
165 }
166 return out
167 }
168
169 f.Fuzz(func(t *testing.T, b []byte) {
170 validRFC7159 := isValid(DecodeOptions{AllowInvalidUTF8: true, AllowDuplicateNames: true}, b)
171 validRFC8259 := isValid(DecodeOptions{AllowInvalidUTF8: false, AllowDuplicateNames: true}, b)
172 validRFC7493 := isValid(DecodeOptions{AllowInvalidUTF8: false, AllowDuplicateNames: false}, b)
173 switch {
174 case !validRFC7159 && validRFC8259:
175 t.Errorf("invalid input per RFC 7159 implies invalid per RFC 8259")
176 case !validRFC8259 && validRFC7493:
177 t.Errorf("invalid input per RFC 8259 implies invalid per RFC 7493")
178 }
179
180 gotValid := RawValue(b).IsValid()
181 wantValid := validRFC7493
182 if gotValid != wantValid {
183 t.Errorf("RawValue.IsValid = %v, want %v", gotValid, wantValid)
184 }
185
186 gotCompacted := RawValue(string(b))
187 gotCompactOk := gotCompacted.Compact() == nil
188 wantCompactOk := validRFC7159
189 if !bytes.Equal(stripWhitespace(gotCompacted), stripWhitespace(b)) {
190 t.Errorf("stripWhitespace(RawValue.Compact) = %s, want %s", stripWhitespace(gotCompacted), stripWhitespace(b))
191 }
192 if !reflect.DeepEqual(unmarshal(gotCompacted), unmarshal(b)) {
193 t.Errorf("unmarshal(RawValue.Compact) = %s, want %s", unmarshal(gotCompacted), unmarshal(b))
194 }
195 if gotCompactOk != wantCompactOk {
196 t.Errorf("RawValue.Compact success mismatch: got %v, want %v", gotCompactOk, wantCompactOk)
197 }
198
199 gotIndented := RawValue(string(b))
200 gotIndentOk := gotIndented.Indent("", " ") == nil
201 wantIndentOk := validRFC7159
202 if !bytes.Equal(stripWhitespace(gotIndented), stripWhitespace(b)) {
203 t.Errorf("stripWhitespace(RawValue.Indent) = %s, want %s", stripWhitespace(gotIndented), stripWhitespace(b))
204 }
205 if !reflect.DeepEqual(unmarshal(gotIndented), unmarshal(b)) {
206 t.Errorf("unmarshal(RawValue.Indent) = %s, want %s", unmarshal(gotIndented), unmarshal(b))
207 }
208 if gotIndentOk != wantIndentOk {
209 t.Errorf("RawValue.Indent success mismatch: got %v, want %v", gotIndentOk, wantIndentOk)
210 }
211
212 gotCanonicalized := RawValue(string(b))
213 gotCanonicalizeOk := gotCanonicalized.Canonicalize() == nil
214 wantCanonicalizeOk := validRFC7493
215 if !reflect.DeepEqual(unmarshal(gotCanonicalized), unmarshal(b)) {
216 t.Errorf("unmarshal(RawValue.Canonicalize) = %s, want %s", unmarshal(gotCanonicalized), unmarshal(b))
217 }
218 if gotCanonicalizeOk != wantCanonicalizeOk {
219 t.Errorf("RawValue.Canonicalize success mismatch: got %v, want %v", gotCanonicalizeOk, wantCanonicalizeOk)
220 }
221 })
222 }
223
224 func FuzzEqualFold(f *testing.F) {
225 for _, tt := range equalFoldTestdata {
226 f.Add([]byte(tt.in1), []byte(tt.in2))
227 }
228
229 equalFoldSimple := func(x, y []byte) bool {
230 strip := func(b []byte) []byte {
231 return bytes.Map(func(r rune) rune {
232 if r == '_' || r == '-' {
233 return -1
234 }
235 return r
236 }, b)
237 }
238 return bytes.EqualFold(strip(x), strip(y))
239 }
240
241 f.Fuzz(func(t *testing.T, s1, s2 []byte) {
242
243 got := equalFold(s1, s2)
244 want := equalFoldSimple(s1, s2)
245 if got != want {
246 t.Errorf("equalFold(%q, %q) = %v, want %v", s1, s2, got, want)
247 }
248 })
249 }
250
View as plain text