Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix typed nil hook support #278

Closed
wants to merge 43 commits into from

Conversation

adriansmares
Copy link

@adriansmares adriansmares commented Mar 29, 2022

Typed nils which are the result of a type decoding hook seem to result in incorrect decoding behavior. Specifically, the nil is turned into an actual value due to the way the nil check works, instead of preserving the nil. Previously we were returning just untyped nils but ever since #205 this seems to no longer be supported while chaining multiple hooks.

I've added a test which reproduces this issue, and a possible fix.

cc @mitchellh

A *customType2 `mapstructure:"a"`
}

for i, marshalledConfig := range []map[string]interface{}{
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first test (which won't use the decoding hooks) works passes just fine without any changes.

if s == "" {
// Returning an untyped nil here would cause a panic, as `from.Type()`
// is invalid for nil.
return (*customType1)(nil), nil
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The panic trace is:

--- FAIL: TestTypedNilPostHooks (0.00s)
    --- FAIL: TestTypedNilPostHooks/1 (0.00s)
panic: reflect: call of reflect.Value.Type on zero Value [recovered]
	panic: reflect: call of reflect.Value.Type on zero Value

goroutine 8 [running]:
testing.tRunner.func1.2({0x56fdc0, 0xc00000e120})
	/usr/local/go/src/testing/testing.go:1389 +0x24e
testing.tRunner.func1()
	/usr/local/go/src/testing/testing.go:1392 +0x39f
panic({0x56fdc0, 0xc00000e120})
	/usr/local/go/src/runtime/panic.go:838 +0x207
reflect.Value.Type({0x0?, 0x0?, 0x5d4e28?})
	/usr/local/go/src/reflect/value.go:2451 +0x12e
github.com/mitchellh/mapstructure.DecodeHookExec({0x571d40?, 0x5a4ed0?}, {0x0?, 0x0?, 0x570840?}, {0x564e80?, 0xc000060df0?, 0x573d00?})
	/home/adriansmares/projects/mapstructure/decode_hooks.go:47 +0x11d
github.com/mitchellh/mapstructure.ComposeDecodeHookFunc.func1({0x56a6a0?, 0x5d3ad0?, 0xc00013d358?}, {0x564e80?, 0xc000060df0?, 0xffffffffffffffff?})
	/home/adriansmares/projects/mapstructure/decode_hooks.go:69 +0x10c
github.com/mitchellh/mapstructure.DecodeHookExec({0x570840?, 0xc00006a140?}, {0x56a6a0?, 0x5d3ad0?, 0xc00013d3b8?}, {0x564e80?, 0xc000060df0?, 0x55fca9?})
	/home/adriansmares/projects/mapstructure/decode_hooks.go:51 +0xd3
github.com/mitchellh/mapstructure.(*Decoder).decode(0xc000010058, {0x55fca9, 0x1}, {0x56a6a0?, 0x5d3ad0?}, {0x564e80?, 0xc000060df0?, 0x10?})
	/home/adriansmares/projects/mapstructure/mapstructure.go:440 +0x179
github.com/mitchellh/mapstructure.(*Decoder).decodeStructFromMap(0xc000010058, {0x0, 0x0}, {0x571500?, 0xc00007e870?, 0x1?}, {0x57b740?, 0xc000060df0?, 0xc00006a120?})
	/home/adriansmares/projects/mapstructure/mapstructure.go:1382 +0x1470
github.com/mitchellh/mapstructure.(*Decoder).decodeStruct(0x570840?, {0x0, 0x0}, {0x571500?, 0xc00007e870?}, {0x57b740?, 0xc000060df0?, 0x203000?})
	/home/adriansmares/projects/mapstructure/mapstructure.go:1208 +0x4ab
github.com/mitchellh/mapstructure.(*Decoder).decode(0xc000010058, {0x0, 0x0}, {0x571500?, 0xc00007e870?}, {0x57b740?, 0xc000060df0?, 0x48?})
	/home/adriansmares/projects/mapstructure/mapstructure.go:463 +0x3cf
github.com/mitchellh/mapstructure.(*Decoder).Decode(0xc000010058, {0x571500, 0xc00007e870})
	/home/adriansmares/projects/mapstructure/mapstructure.go:398 +0xd8
github.com/mitchellh/mapstructure.TestTypedNilPostHooks.func1(0xc000115380)
	/home/adriansmares/projects/mapstructure/mapstructure_test.go:2551 +0x14e
testing.tRunner(0xc000115380, 0xc000060de0)
	/usr/local/go/src/testing/testing.go:1439 +0x102
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:1486 +0x35f
FAIL	github.com/mitchellh/mapstructure	0.005s
FAIL

It seems to me that returning nil from a type decoding hook is not supported (was it supported in the first place ?)

@@ -993,7 +993,7 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b
// pointer to be nil as well.
isNil := data == nil
if !isNil {
switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() {
switch v := reflect.ValueOf(data); v.Kind() {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure if this change is correct. I don't understand why Indirect was used here before, given that the nulalbility of data is important here, not the value to which data points.

Are there any other call sites that may require updates ?

Anton N. Ryabkov and others added 2 commits June 9, 2022 14:03
@adriansmares
Copy link
Author

Pinging @mitchellh .

nolag and others added 22 commits October 30, 2023 11:52
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Add decode hooks for netip Addr and AddrPort
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Dereference multiple pointers when decoding to maps
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
fix: StringToSliceHookFunc incorrectly triggered when parsing []byte
…d-fields

Fix untagged field decoding in case of decode to struct
sagikazarmark and others added 19 commits December 18, 2023 19:16
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
feature: add StringToBasicTypeHookFunc and support complex
Add an example showing how to use a DecodeHookFunc to parse a custom …
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants