From 63cde0dfe2481856bcfc2184477b26df770f19d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Proch=C3=A1zka?= Date: Tue, 18 Apr 2023 19:25:16 +0200 Subject: [PATCH] prevent panic in TextUnmarshallerHookFunc if reflect.Kind is reflect.String, it doesn't necessary means it's `string` type. It can be string-based type --- decode_hooks.go | 6 +++++- decode_hooks_test.go | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/decode_hooks.go b/decode_hooks.go index 3a754ca..c1f99da 100644 --- a/decode_hooks.go +++ b/decode_hooks.go @@ -271,7 +271,11 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType { if !ok { return data, nil } - if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil { + str, ok := data.(string) + if !ok { + str = reflect.Indirect(reflect.ValueOf(&data)).Elem().String() + } + if err := unmarshaller.UnmarshalText([]byte(str)); err != nil { return nil, err } return result, nil diff --git a/decode_hooks_test.go b/decode_hooks_test.go index bf02952..b773960 100644 --- a/decode_hooks_test.go +++ b/decode_hooks_test.go @@ -1,6 +1,7 @@ package mapstructure import ( + "encoding/json" "errors" "math/big" "net" @@ -542,6 +543,8 @@ func TestStructToMapHookFuncTabled(t *testing.T) { } func TestTextUnmarshallerHookFunc(t *testing.T) { + type MyString string + cases := []struct { f, t reflect.Value result interface{} @@ -550,8 +553,9 @@ func TestTextUnmarshallerHookFunc(t *testing.T) { {reflect.ValueOf("42"), reflect.ValueOf(big.Int{}), big.NewInt(42), false}, {reflect.ValueOf("invalid"), reflect.ValueOf(big.Int{}), nil, true}, {reflect.ValueOf("5"), reflect.ValueOf("5"), "5", false}, + {reflect.ValueOf(json.Number("42")), reflect.ValueOf(big.Int{}), big.NewInt(42), false}, + {reflect.ValueOf(MyString("42")), reflect.ValueOf(big.Int{}), big.NewInt(42), false}, } - for i, tc := range cases { f := TextUnmarshallerHookFunc() actual, err := DecodeHookExec(f, tc.f, tc.t)