Skip to content

Commit

Permalink
fix(reflect): deep nested struct cause panic
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaost committed Dec 4, 2024
1 parent 7402993 commit d675e92
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 11 deletions.
35 changes: 24 additions & 11 deletions internal/reflect/desc.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,36 @@ func newStructDescAndPrefetch(t reflect.Type) (*structDesc, error) {

func prefetchSubStructDesc(d *structDesc) error {
for i := range d.fields {
var t *tType
f := d.fields[i]
if f.Type.T == tSTRUCT {
t = f.Type
} else if f.Type.T == tMAP && f.Type.V.T == tSTRUCT {
t = f.Type.V
} else if f.Type.T == tLIST && f.Type.V.T == tSTRUCT {
t = f.Type.V
} else {
continue
switch f.Type.T {
case tSTRUCT, tMAP, tLIST, tSET:
if err := fetchStructDesc(f.Type); err != nil {
return err
}
}
sd, err := newStructDescAndPrefetch(t.RT)
}
return nil
}

func fetchStructDesc(t *tType) error {
if t.T == tMAP {
err := fetchStructDesc(t.K)
if err != nil {
return err
}
t.Sd = sd
return fetchStructDesc(t.V)
}
if t.T == tLIST || t.T == tSET {
return fetchStructDesc(t.V)
}
if t.T != tSTRUCT || t.Sd != nil {
return nil
}
sd, err := newStructDescAndPrefetch(t.RT)
if err != nil {
return err
}
t.Sd = sd
return nil
}

Expand Down
25 changes: 25 additions & 0 deletions internal/reflect/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,28 @@ func TestEncodeUnknownFields(t *testing.T) {
assert.Equal(t, n, len(b))
assert.Contains(t, string(b), string(append([]byte("helloworld")[:], byte(tSTOP))))
}

func TestNestedListMapStruct(t *testing.T) {
type Msg1 struct {
A string `frugal:"1,default,string"`
B string `frugal:"2,default,string"`
}
type Msg2 struct {
Msgs []map[string]*Msg1 `thrift:"item_list,2" frugal:"2,default,list<map<string:Msg1>>" json:"item_list"`
}
p := &Msg2{}
p.Msgs = make([]map[string]*Msg1, 0, 1)
p.Msgs = append(p.Msgs, map[string]*Msg1{})
p.Msgs[0]["32"] = &Msg1{A: "Hello", B: "World"}

b := make([]byte, EncodedSize(p))
x, err := Append(b[:0], p)
require.NoError(t, err)
require.Equal(t, len(x), len(b))

p2 := &Msg2{}
i, err := Decode(x, p2)
require.NoError(t, err)
require.Equal(t, i, len(b))
require.Equal(t, p, p2)
}

0 comments on commit d675e92

Please sign in to comment.