proto: return error from Marshal if a message encodes to > 2GiB While this check could be done before marshalling, it shouldn't occur frequently and thus would slow down proto encoding on average.
diff --git a/proto/encode.go b/proto/encode.go index eb7e047..401c114 100644 --- a/proto/encode.go +++ b/proto/encode.go
@@ -70,6 +70,10 @@ // ErrNil is the error returned if Marshal is called with nil. ErrNil = errors.New("proto: Marshal called with nil") + + // ErrTooLarge is the error returned if Marshal is called with a + // message that encodes to >2GB. + ErrTooLarge = errors.New("proto: message encodes to over 2 GB") ) // The fundamental encoders that put bytes on the wire. @@ -78,6 +82,10 @@ const maxVarintBytes = 10 // maximum length of a varint +// maxMarshalSize is the largest allowed size of an encoded protobuf, +// since C++ and Java use signed int32s for the size. +const maxMarshalSize = 1<<31 - 1 + // EncodeVarint returns the varint encoding of x. // This is the format for the // int32, int64, uint32, uint64, bool, and enum @@ -277,6 +285,9 @@ stats.Encode++ } + if len(p.buf) > maxMarshalSize { + return ErrTooLarge + } return err } @@ -1220,6 +1231,9 @@ return err } } + if len(o.buf) > maxMarshalSize { + return ErrTooLarge + } } } @@ -1236,6 +1250,9 @@ // Add unrecognized fields at the end. if prop.unrecField.IsValid() { v := *structPointer_Bytes(base, prop.unrecField) + if len(o.buf)+len(v) > maxMarshalSize { + return ErrTooLarge + } if len(v) > 0 { o.buf = append(o.buf, v...) }