From 6c2a694486d1206cc495744d61b377fc321bafed Mon Sep 17 00:00:00 2001 From: Sergey Vilgelm Date: Thu, 9 Feb 2023 22:28:38 -0800 Subject: [PATCH] track the visited structures in the checkStruct fucntion fix #16 with stack overflow issue when a struct has the fields of self type --- musttag.go | 10 +++++++--- testdata/src/tests/tests.go | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/musttag.go b/musttag.go index 121777b..4371cd1 100644 --- a/musttag.go +++ b/musttag.go @@ -171,7 +171,7 @@ func run(pass *analysis.Pass, funcs map[string]Func) (any, error) { return // not a struct argument. } - reportPos, ok := checkStruct(s, fn.Tag) + reportPos, ok := checkStruct(s, fn.Tag, make(map[string]struct{})) if ok { return // nothing to report. } @@ -222,7 +222,8 @@ func parseStruct(t types.Type, pos token.Pos) (*structInfo, bool) { // checkStruct recursively checks the given struct and returns the position for report, // in case one of its fields is missing the tag. -func checkStruct(s *structInfo, tag string) (token.Pos, bool) { +func checkStruct(s *structInfo, tag string, visited map[string]struct{}) (token.Pos, bool) { + visited[s.String()] = struct{}{} for i := 0; i < s.NumFields(); i++ { if !s.Field(i).Exported() { continue @@ -238,7 +239,10 @@ func checkStruct(s *structInfo, tag string) (token.Pos, bool) { if !ok { continue } - if pos, ok := checkStruct(nested, tag); !ok { + if _, ok := visited[nested.String()]; ok { + continue + } + if pos, ok := checkStruct(nested, tag, visited); !ok { return pos, false } } diff --git a/testdata/src/tests/tests.go b/testdata/src/tests/tests.go index 007328c..7a2013f 100644 --- a/testdata/src/tests/tests.go +++ b/testdata/src/tests/tests.go @@ -468,3 +468,14 @@ func nonStructArgument() { custom.Marshal(0) custom.Unmarshal(nil, &[]int{}) } + +// test for stack overflow issue: https://github.com/junk1tm/musttag/issues/16 +func selfType() { + type Human struct { + Mom *Human `json:"mom"` + Dad *Human `json:"dad"` + Children []*Human `json:"children"` + } + var v *Human + json.Marshal(v) +}