Skip to content

Commit

Permalink
encoding/protodelim: fix handling of io.EOF
Browse files Browse the repository at this point in the history
Before this change, when encountering an io.EOF after reading at least
one byte, the zero value byte was — incorrectly — appended to sizeBuf,
and the io.EOF was ignored, resulting in a complete varint (0 has no
continuation bit), which in turn resulted in incorrect unmarshalling.

Change-Id: If06d45039d998eaddf91d0864814bb31d4cb7ae0
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/505555
Reviewed-by: Lasse Folger <[email protected]>
Reviewed-by: Damien Neil <[email protected]>
  • Loading branch information
stapelberg committed Jun 26, 2023
1 parent fc47fdd commit 59a8581
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
6 changes: 5 additions & 1 deletion encoding/protodelim/protodelim.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ func (o UnmarshalOptions) UnmarshalFrom(r Reader, m proto.Message) error {
sizeBuf := sizeArr[:0]
for i := range sizeArr {
b, err := r.ReadByte()
if err != nil && (err != io.EOF || i == 0) {
if err != nil {
// Immediate EOF is unexpected.
if err == io.EOF && i != 0 {
break
}
return err
}
sizeBuf = append(sizeBuf, b)
Expand Down
17 changes: 17 additions & 0 deletions encoding/protodelim/protodelim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package protodelim_test
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"io"
"testing"
Expand Down Expand Up @@ -202,3 +203,19 @@ func TestUnmarshalFrom_UnexpectedEOF(t *testing.T) {
t.Errorf("protodelim.UnmarshalFrom(size-only buf, _) = %v, want %v", got, want)
}
}

func TestUnmarshalFrom_PrematureHeader(t *testing.T) {
var data = []byte{128} // continuation bit set
err := protodelim.UnmarshalFrom(bytes.NewReader(data[:]), nil)
if got, want := err, io.ErrUnexpectedEOF; !errors.Is(got, want) {
t.Errorf("protodelim.UnmarshalFrom(%#v, nil) = %#v; want = %#v", data, got, want)
}
}

func TestUnmarshalFrom_InvalidVarint(t *testing.T) {
var data = bytes.Repeat([]byte{128}, 2*binary.MaxVarintLen64) // continuation bit set
err := protodelim.UnmarshalFrom(bytes.NewReader(data[:]), nil)
if err == nil {
t.Errorf("protodelim.UnmarshalFrom unexpectedly did not error on invalid varint")
}
}

0 comments on commit 59a8581

Please sign in to comment.