Merge 466e46f65fe94bb8b69e7fbadf50ff9a0789741d into 626d55b0c02937645c21774cacc021713de88604

This commit is contained in:
Frank Mai 2024-06-23 11:33:16 +08:00 committed by GitHub
commit 952b16ee4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 6 deletions

View File

@ -19,6 +19,7 @@ import (
var (
errUnknownType = errors.New("unknown type")
errRecursionTooDeep = errors.New("recursion too deep")
// ErrConvertMapStringSlice can not convert to map[string][]string
ErrConvertMapStringSlice = errors.New("can not convert to map slices of strings")
@ -75,14 +76,18 @@ func (form formSource) TrySet(value reflect.Value, field reflect.StructField, ta
}
func mappingByPtr(ptr any, setter setter, tag string) error {
_, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag)
_, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag, 0)
return err
}
func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) {
func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string, deepth int) (bool, error) {
if field.Tag.Get(tag) == "-" { // just ignoring this field
return false, nil
}
if deepth >= 1000 {
// avoid causing stackoverflow.
return false, errRecursionTooDeep
}
vKind := value.Kind()
@ -93,7 +98,7 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag
isNew = true
vPtr = reflect.New(value.Type().Elem())
}
isSet, err := mapping(vPtr.Elem(), field, setter, tag)
isSet, err := mapping(vPtr.Elem(), field, setter, tag, deepth+1)
if err != nil {
return false, err
}
@ -122,7 +127,7 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag
if sf.PkgPath != "" && !sf.Anonymous { // unexported
continue
}
ok, err := mapping(value.Field(i), sf, setter, tag)
ok, err := mapping(value.Field(i), sf, setter, tag, deepth+1)
if err != nil {
return false, err
}

View File

@ -58,7 +58,7 @@ func TestMappingBaseTypes(t *testing.T) {
field := val.Elem().Type().Field(0)
_, err := mapping(val, emptyField, formSource{field.Name: {tt.form}}, "form")
_, err := mapping(val, emptyField, formSource{field.Name: {tt.form}}, "form", 0)
assert.NoError(t, err, testName)
actual := val.Elem().Field(0).Interface()
@ -318,6 +318,16 @@ func TestMappingMapField(t *testing.T) {
assert.Equal(t, map[string]int{"one": 1}, s.M)
}
func TestMappingCircularRef(t *testing.T) {
type S struct {
S *S `form:"s"`
}
var s S
err := mappingByPtr(&s, formSource{}, "form")
assert.ErrorIs(t, err, errRecursionTooDeep)
}
func TestMappingIgnoredCircularRef(t *testing.T) {
type S struct {
S *S `form:"-"`