diff --git a/fuzz.go b/fuzz.go index 3cc727c..6cfcd55 100644 --- a/fuzz.go +++ b/fuzz.go @@ -1,8 +1,8 @@ -// +build gofuzz - package ndp -func Fuzz(data []byte) int { +// fuzz is a shared function for go-fuzz and tests that verify go-fuzz bugs +// are fixed. +func fuzz(data []byte) int { m, err := ParseMessage(data) if err != nil { return 0 diff --git a/fuzz_test.go b/fuzz_test.go new file mode 100644 index 0000000..cdf6c36 --- /dev/null +++ b/fuzz_test.go @@ -0,0 +1,26 @@ +package ndp + +import "testing" + +func Test_fuzz(t *testing.T) { + tests := []struct { + name string + s string + }{ + { + name: "parse option length", + s: "\x86000000000000000\x01\xc0", + }, + { + name: "prefix information length", + s: "\x86000000000000000\x03\x0100" + + "0000", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _ = fuzz([]byte(tt.s)) + }) + } +} diff --git a/gofuzz.go b/gofuzz.go new file mode 100644 index 0000000..1540ed5 --- /dev/null +++ b/gofuzz.go @@ -0,0 +1,7 @@ +//+build gofuzz + +package ndp + +func Fuzz(data []byte) int { + return fuzz(data) +} diff --git a/option.go b/option.go index 6529ead..e61989b 100644 --- a/option.go +++ b/option.go @@ -207,6 +207,11 @@ func (pi *PrefixInformation) UnmarshalBinary(b []byte) error { return err } + // Guard against incorrect option length. + if raw.Length != piOptLen { + return io.ErrUnexpectedEOF + } + var ( oFlag = (raw.Value[1] & 0x80) != 0 aFlag = (raw.Value[1] & 0x40) != 0 @@ -333,16 +338,17 @@ func parseOptions(b []byte) ([]Option, error) { o = new(RawOption) } + // Verify that we won't advance beyond the end of the byte slice. + if l > len(b[i:]) { + return nil, io.ErrUnexpectedEOF + } + // Unmarshal at the current offset, up to the expected length. if err := o.UnmarshalBinary(b[i : i+l]); err != nil { return nil, err } - // Verify that we won't advance beyond the end of the byte slice, and // Advance to the next option's type field. - if l > len(b[i:]) { - return nil, io.ErrUnexpectedEOF - } i += l options = append(options, o)