// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: MIT package xdr import ( "testing" ) // FuzzDecoder feeds arbitrary bytes through every read of the decoder: // no input may panic, hang or index out of range, and every failure // arrives as an error. func FuzzDecoder(f *testing.F) { f.Add([]byte{0, 0, 0, 1}) f.Add([]byte{0xff, 0xff, 0xff, 0xff}) f.Add([]byte{0, 0, 0, 2, 'a', 'b', 0}) f.Add([]byte{0, 0, 0, 5, 'h', 'e', 'l', 'l', 'o'}) f.Add([]byte{0x7f}) f.Add(make([]byte, 64)) f.Fuzz(func(t *testing.T, data []byte) { d := NewDecoder(data) _, _ = d.Uint32() _, _ = d.Int64() _, _ = d.Uint64() _, _ = d.Bool() _, _ = d.String() _, _ = d.VarOpaque() _, _ = d.FixedOpaque(4) _, _ = d.Raw(3) _ = d.Remaining() // The writers must accept the decoded values back and the // re-decode must agree or fail cleanly. d2 := NewDecoder(data) if s, err := d2.String(); err == nil { again, aerr := NewDecoder(AppendString(nil, s)).String() if aerr != nil || again != s { t.Fatalf("string round trip: %q %v %q", s, aerr, again) } } if o, err := d2.VarOpaque(); err == nil { again, aerr := NewDecoder(AppendVarOpaque(nil, o)).VarOpaque() if aerr != nil || string(again) != string(o) { t.Fatal("opaque round trip") } } }) } // FuzzPadding checks the pad arithmetic against the property that an // encoded value always decodes back to itself, whatever the length. func FuzzPadding(f *testing.F) { f.Add([]byte{}) f.Add([]byte("a")) f.Add([]byte("abc")) f.Add([]byte("abcd")) f.Fuzz(func(t *testing.T, data []byte) { enc := AppendVarOpaque(nil, data) got, err := NewDecoder(enc).VarOpaque() if err != nil { t.Fatalf("decode of a value this package encoded: %v", err) } if string(got) != string(data) { t.Fatalf("round trip: %q became %q", data, got) } }) }