goprotobuf: Handle a non-pointer being passed to MarshalText.
R=r
CC=golang-dev
http://codereview.appspot.com/5876065
diff --git a/proto/text.go b/proto/text.go
index d781c68..f7279ae 100644
--- a/proto/text.go
+++ b/proto/text.go
@@ -408,10 +408,16 @@
aw.complete = true
aw.compact = compact
+ // Reject non-pointer inputs (it's a bad practice to pass potentially large protos around by value).
v := reflect.ValueOf(pb)
- // We should normally be passed a struct, or a pointer to a struct,
- // and we don't want the outer < and > in that case.
+ if v.Kind() != reflect.Ptr {
+ w.Write([]byte("<struct-by-value>"))
+ return
+ }
+
+ // Dereference the received pointer so we don't have outer < and >.
v = reflect.Indirect(v)
+
if v.Kind() == reflect.Struct {
writeStruct(aw, v)
} else {
diff --git a/proto/text_test.go b/proto/text_test.go
index e720bdd..7d8adfb 100644
--- a/proto/text_test.go
+++ b/proto/text_test.go
@@ -53,11 +53,11 @@
Connected: proto.Bool(true),
},
Others: []*pb.OtherMessage{
- &pb.OtherMessage{
+ {
Key: proto.Int64(0xdeadbeef),
Value: []byte{1, 65, 7, 12},
},
- &pb.OtherMessage{
+ {
Weight: proto.Float32(6.022),
Inner: &pb.InnerMessage{
Host: proto.String("lesha.mtv"),
@@ -221,3 +221,12 @@
}
}
}
+
+func TestNonPtrMessage(t *testing.T) {
+ // Ensure we don't panic when we pass a non-pointer to MarshalText.
+ var buf bytes.Buffer
+ proto.MarshalText(&buf, pb.MyMessage{})
+ if s := buf.String(); s != "<struct-by-value>" {
+ t.Errorf("got: %q, want %q", s, "<struct-by-value>")
+ }
+}