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