fix(decode): terminate the schema walk on a self-embedded pointer struct
Assisted-by: GLM 5.3
This commit is contained in:
@@ -255,8 +255,15 @@ type structSchema struct {
|
||||
|
||||
func newStructSchema(t reflect.Type) structSchema {
|
||||
s := structSchema{byName: make(map[string]structFieldLoc, t.NumField())}
|
||||
// A struct may embed a pointer to itself, which is legal Go, so the walk
|
||||
// tracks the struct types on the current path and stops when one repeats;
|
||||
// without the guard the recursion never terminates. A self-promoted key
|
||||
// always loses to the shallower original, so skipping it changes nothing.
|
||||
visiting := map[reflect.Type]bool{}
|
||||
var walk func(t reflect.Type, prefix []int, depth int)
|
||||
walk = func(t reflect.Type, prefix []int, depth int) {
|
||||
visiting[t] = true
|
||||
defer delete(visiting, t)
|
||||
for i := range t.NumField() {
|
||||
f := t.Field(i)
|
||||
if f.PkgPath != "" { // unexported
|
||||
@@ -277,7 +284,9 @@ func newStructSchema(t reflect.Type) structSchema {
|
||||
}
|
||||
switch {
|
||||
case ft.Kind() == reflect.Struct && !isScalarStruct(ft):
|
||||
walk(ft, path, depth+1)
|
||||
if !visiting[ft] {
|
||||
walk(ft, path, depth+1)
|
||||
}
|
||||
continue
|
||||
case ft.Kind() == reflect.Map && ft.Key().Kind() == reflect.String:
|
||||
s.embedMaps = append(s.embedMaps, path)
|
||||
|
||||
Reference in New Issue
Block a user