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...)
}