Skip to content

Commit 33d4760

Browse files
committed
merged in golang/protobuf commit 4c88cc3f1a34ffade77b79abc53335d1e511f25b - all: fix reflect.Value.Interface races.
1 parent f99a381 commit 33d4760

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

jsonpb/jsonpb.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ type isWkt interface {
164164
XXX_WellKnownType() string
165165
}
166166

167+
var (
168+
wktType = reflect.TypeOf((*isWkt)(nil)).Elem()
169+
messageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
170+
)
171+
167172
// marshalObject writes a struct to the Writer.
168173
func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error {
169174
if jsm, ok := v.(JSONPBMarshaler); ok {
@@ -551,7 +556,8 @@ func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v refle
551556

552557
// Handle well-known types.
553558
// Most are handled up in marshalObject (because 99% are messages).
554-
if wkt, ok := v.Interface().(isWkt); ok {
559+
if v.Type().Implements(wktType) {
560+
wkt := v.Interface().(isWkt)
555561
switch wkt.XXX_WellKnownType() {
556562
case "NullValue":
557563
out.write("null")
@@ -1422,8 +1428,8 @@ func checkRequiredFields(pb proto.Message) error {
14221428
}
14231429

14241430
func checkRequiredFieldsInValue(v reflect.Value) error {
1425-
if pm, ok := v.Interface().(proto.Message); ok {
1426-
return checkRequiredFields(pm)
1431+
if v.Type().Implements(messageType) {
1432+
return checkRequiredFields(v.Interface().(proto.Message))
14271433
}
14281434
return nil
14291435
}

proto/all_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ import (
4545
"testing"
4646
"time"
4747

48+
"github.com/gogo/protobuf/jsonpb"
4849
. "github.com/gogo/protobuf/proto"
4950
pb3 "github.com/gogo/protobuf/proto/proto3_proto"
5051
. "github.com/gogo/protobuf/proto/test_proto"
52+
descriptorpb "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
5153
)
5254

5355
var globalO *Buffer
@@ -2509,3 +2511,33 @@ func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) {
25092511
p2.Unmarshal(pbd)
25102512
}
25112513
}
2514+
2515+
// TestRace tests whether there are races among the different marshalers.
2516+
func TestRace(t *testing.T) {
2517+
m := &descriptorpb.FileDescriptorProto{
2518+
Options: &descriptorpb.FileOptions{
2519+
GoPackage: String("path/to/my/package"),
2520+
},
2521+
}
2522+
2523+
wg := &sync.WaitGroup{}
2524+
defer wg.Wait()
2525+
2526+
wg.Add(1)
2527+
go func() {
2528+
defer wg.Done()
2529+
Marshal(m)
2530+
}()
2531+
2532+
wg.Add(1)
2533+
go func() {
2534+
defer wg.Done()
2535+
(&jsonpb.Marshaler{}).MarshalToString(m)
2536+
}()
2537+
2538+
wg.Add(1)
2539+
go func() {
2540+
defer wg.Done()
2541+
_ = m.String()
2542+
}()
2543+
}

proto/text.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
476476
return nil
477477
}
478478

479+
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
480+
479481
// writeAny writes an arbitrary field.
480482
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
481483
v = reflect.Indirect(v)
@@ -589,8 +591,8 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
589591
// mutating this value.
590592
v = v.Addr()
591593
}
592-
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
593-
text, err := etm.MarshalText()
594+
if v.Type().Implements(textMarshalerType) {
595+
text, err := v.Interface().(encoding.TextMarshaler).MarshalText()
594596
if err != nil {
595597
return err
596598
}

0 commit comments

Comments
 (0)