diff --git a/memuvarint.go b/memuvarint.go index 48a57f9c..fc82adce 100644 --- a/memuvarint.go +++ b/memuvarint.go @@ -16,6 +16,7 @@ package zap import ( "fmt" + "io" ) type memUvarintReader struct { @@ -50,6 +51,10 @@ func (r *memUvarintReader) ReadUvarint() (uint64, error) { var S = r.S for { + if C >= len(S) { + r.C = C + return 0, io.ErrUnexpectedEOF + } b := S[C] C++ diff --git a/memuvarint_test.go b/memuvarint_test.go index a5b3a503..6bdd21ac 100644 --- a/memuvarint_test.go +++ b/memuvarint_test.go @@ -17,10 +17,25 @@ package zap import ( "bytes" "encoding/binary" + "errors" + "io" "math" "testing" ) +func TestMemUvarintReaderReturnsUnexpectedEOFForTruncatedValue(t *testing.T) { + for _, input := range [][]byte{{0x80}, {0x80, 0x80}, {0xff, 0xff, 0xff}} { + reader := newMemUvarintReader(input) + _, err := reader.ReadUvarint() + if !errors.Is(err, io.ErrUnexpectedEOF) { + t.Fatalf("ReadUvarint(%x) error = %v, want %v", input, err, io.ErrUnexpectedEOF) + } + if reader.C != len(input) { + t.Fatalf("ReadUvarint(%x) consumed %d bytes, want %d", input, reader.C, len(input)) + } + } +} + func BenchmarkUvarint(b *testing.B) { n, buf := generateCommonUvarints(64, 512)