From 94de2ac70cdd7b74f706c72f4889499df1e93dcd Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 11 Nov 2022 16:22:59 +0100 Subject: [PATCH 1/7] fix: proposal.String() panics with nested Anys --- proto/text.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/proto/text.go b/proto/text.go index 4bb1a049..b593a8bc 100644 --- a/proto/text.go +++ b/proto/text.go @@ -482,6 +482,11 @@ var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) + // if cannot set value, then it is unexported - skip + if !v.CanSet() { + return nil + } + if props != nil { if len(props.CustomType) > 0 { custom, ok := v.Interface().(Marshaler) @@ -551,6 +556,16 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert // Other values are handled below. } + // Uints are no interfaces + if v.Kind() == reflect.Uint || + v.Kind() == reflect.Uint8 || + v.Kind() == reflect.Uint16 || + v.Kind() == reflect.Uint32 || + v.Kind() == reflect.Uint64 { + _, err := fmt.Fprintf(w, "%d", v.Uint()) + return err + } + // We don't attempt to serialise every possible value type; only those // that can occur in protocol buffers. switch v.Kind() { From 1575f345aefeb15b9ade40fced39abf502a51d6f Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 11 Nov 2022 17:35:24 +0100 Subject: [PATCH 2/7] updates --- proto/text.go | 10 ++++++++-- proto/text_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/proto/text.go b/proto/text.go index b593a8bc..1a25bfb3 100644 --- a/proto/text.go +++ b/proto/text.go @@ -267,6 +267,12 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { sprops := GetProperties(st) for i := 0; i < sv.NumField(); i++ { fv := sv.Field(i) + + // skip unexported fields + if !fv.CanSet() { + continue + } + props := sprops.Prop[i] name := st.Field(i).Name @@ -482,7 +488,7 @@ var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) - // if cannot set value, then it is unexported - skip + // skip unexported fields if !v.CanSet() { return nil } @@ -556,7 +562,7 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert // Other values are handled below. } - // Uints are no interfaces + // Uints are not interfaces if v.Kind() == reflect.Uint || v.Kind() == reflect.Uint8 || v.Kind() == reflect.Uint16 || diff --git a/proto/text_test.go b/proto/text_test.go index dc3abbf7..402c1b48 100644 --- a/proto/text_test.go +++ b/proto/text_test.go @@ -516,3 +516,28 @@ func TestRacyMarshal(t *testing.T) { }() } } + +func TestAny(t *testing.T) { + any := &pb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")} + proto.SetExtension(any, pb.E_Ext_Text, proto.String("bar")) + b, err := proto.Marshal(any) + if err != nil { + panic(err) + } + m := &proto3pb.Message{ + Name: "David", + ResultCount: 47, + Anything: &types.Any{TypeUrl: proto.MessageName(any), Value: b}, + } + + expected := `name: "David" + result_count: 47 + anything: < + type_url: "test_proto.MyMessage" + value: "\302\006\003bar\010/\022\005David" + >` + got := proto.MarshalTextString(m) + if strings.EqualFold(expected, got) { + t.Errorf("got = %s, want %s", expected, got) + } +} From 7c3088b8ae47eae46645f78e9f7833634729a13f Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 11 Nov 2022 18:16:41 +0100 Subject: [PATCH 3/7] fix tests --- proto/text.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/proto/text.go b/proto/text.go index 1a25bfb3..7a0ecf88 100644 --- a/proto/text.go +++ b/proto/text.go @@ -488,11 +488,6 @@ var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) - // skip unexported fields - if !v.CanSet() { - return nil - } - if props != nil { if len(props.CustomType) > 0 { custom, ok := v.Interface().(Marshaler) From 015ba5e9e3c3d0dcabbb02dbc1bf34f112d77167 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Sat, 12 Nov 2022 13:02:15 +0100 Subject: [PATCH 4/7] updates --- proto/text.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/proto/text.go b/proto/text.go index 7a0ecf88..76ed47d2 100644 --- a/proto/text.go +++ b/proto/text.go @@ -487,6 +487,7 @@ var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() // writeAny writes an arbitrary field. func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) + k := v.Kind() if props != nil { if len(props.CustomType) > 0 { @@ -539,7 +540,7 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert } // Floats have special cases. - if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + if k == reflect.Float32 || k == reflect.Float64 { x := v.Float() var b []byte switch { @@ -557,19 +558,22 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert // Other values are handled below. } - // Uints are not interfaces - if v.Kind() == reflect.Uint || - v.Kind() == reflect.Uint8 || - v.Kind() == reflect.Uint16 || - v.Kind() == reflect.Uint32 || - v.Kind() == reflect.Uint64 { + // Handle Uints + if k == reflect.Uint || + k == reflect.Uint8 || + k == reflect.Uint16 || + k == reflect.Uint32 || + k == reflect.Uint64 { _, err := fmt.Fprintf(w, "%d", v.Uint()) return err } // We don't attempt to serialise every possible value type; only those // that can occur in protocol buffers. - switch v.Kind() { + switch k { + case reflect.Bool: + _, err := fmt.Fprint(w, v.Bool()) + return err case reflect.Slice: // Should only be a []byte; repeated fields are handled in writeStruct. if err := writeString(w, string(v.Bytes())); err != nil { From 5ba18d325fc552dddfdce395905641f5225ebc50 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Sat, 12 Nov 2022 15:49:58 +0100 Subject: [PATCH 5/7] fix tests --- proto/text.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proto/text.go b/proto/text.go index 76ed47d2..7dbf92f3 100644 --- a/proto/text.go +++ b/proto/text.go @@ -268,14 +268,14 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { for i := 0; i < sv.NumField(); i++ { fv := sv.Field(i) - // skip unexported fields - if !fv.CanSet() { - continue - } - props := sprops.Prop[i] name := st.Field(i).Name + // skip unexported fields (i.e first letter is lowercase) + if name[0] != strings.ToUpper(name)[0] { + continue + } + if name == "XXX_NoUnkeyedLiteral" { continue } From 5ae12fbe3491bbfb5cad21ac54dcc87619e9baf9 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Sat, 12 Nov 2022 16:06:14 +0100 Subject: [PATCH 6/7] add changelog and prepare for release --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1328aba5..96906cb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,11 @@ ## [Unreleased] +## [v1.4.3](https://github.com/cosmos/gogoproto/releases/tag/v1.4.2) - 2022-10-14 + ### Bug Fixes +- [#24](https://github.com/cosmos/gogoproto/pull/24) Fix `CompactTextString` panics with nested Anys and private fields. - [#14](https://github.com/cosmos/gogoproto/pull/14) Fix `make regenerate`. ## [v1.4.2](https://github.com/cosmos/gogoproto/releases/tag/v1.4.2) - 2022-09-14 From 902db449f6e3100a174ffc381d2bc14f6c582323 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Mon, 14 Nov 2022 11:10:00 +0100 Subject: [PATCH 7/7] remove unecessary addition --- proto/text.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/proto/text.go b/proto/text.go index 7dbf92f3..75c045e1 100644 --- a/proto/text.go +++ b/proto/text.go @@ -558,22 +558,9 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert // Other values are handled below. } - // Handle Uints - if k == reflect.Uint || - k == reflect.Uint8 || - k == reflect.Uint16 || - k == reflect.Uint32 || - k == reflect.Uint64 { - _, err := fmt.Fprintf(w, "%d", v.Uint()) - return err - } - // We don't attempt to serialise every possible value type; only those // that can occur in protocol buffers. switch k { - case reflect.Bool: - _, err := fmt.Fprint(w, v.Bool()) - return err case reflect.Slice: // Should only be a []byte; repeated fields are handled in writeStruct. if err := writeString(w, string(v.Bytes())); err != nil {