Skip to content

Commit cdec085

Browse files
thomas11rsc
authored andcommitted
encoding/json: don't panic marshaling anonymous non-struct field
Add a check for this case and don't try to follow the anonymous type's non-existent fields. Fixes #4474. R=rsc CC=golang-dev https://golang.org/cl/6945065
1 parent a29702f commit cdec085

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

src/pkg/encoding/json/encode.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -617,13 +617,20 @@ func typeFields(t reflect.Type) []field {
617617
index := make([]int, len(f.index)+1)
618618
copy(index, f.index)
619619
index[len(f.index)] = i
620+
621+
ft := sf.Type
622+
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
623+
// Follow pointer.
624+
ft = ft.Elem()
625+
}
626+
620627
// Record found field and index sequence.
621-
if name != "" || !sf.Anonymous {
628+
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
622629
tagged := name != ""
623630
if name == "" {
624631
name = sf.Name
625632
}
626-
fields = append(fields, field{name, tagged, index, sf.Type,
633+
fields = append(fields, field{name, tagged, index, ft,
627634
opts.Contains("omitempty"), opts.Contains("string")})
628635
if count[f.typ] > 1 {
629636
// If there were multiple instances, add a second,
@@ -636,11 +643,6 @@ func typeFields(t reflect.Type) []field {
636643
}
637644

638645
// Record new anonymous struct to explore in next round.
639-
ft := sf.Type
640-
if ft.Name() == "" {
641-
// Must be pointer.
642-
ft = ft.Elem()
643-
}
644646
nextCount[ft]++
645647
if nextCount[ft] == 1 {
646648
next = append(next, field{name: ft.Name(), index: index, typ: ft})

src/pkg/encoding/json/encode_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,23 @@ func TestMarshalerEscaping(t *testing.T) {
186186
t.Errorf("got %q, want %q", got, want)
187187
}
188188
}
189+
190+
type IntType int
191+
192+
type MyStruct struct {
193+
IntType
194+
}
195+
196+
func TestAnonymousNonstruct(t *testing.T) {
197+
var i IntType = 11
198+
a := MyStruct{i}
199+
const want = `{"IntType":11}`
200+
201+
b, err := Marshal(a)
202+
if err != nil {
203+
t.Fatalf("Marshal: %v", err)
204+
}
205+
if got := string(b); got != want {
206+
t.Errorf("got %q, want %q", got, want)
207+
}
208+
}

0 commit comments

Comments
 (0)