pelletier / go-toml

Go library for the TOML file format
https://github.com/pelletier/go-toml
Other
1.68k stars 208 forks source link

Decode toml failed on the special format #866

Closed ThisIsSun closed 1 year ago

ThisIsSun commented 1 year ago

Describe the bug The following test case shows an error in decoding toml with special format. The 'bad' test case looks the same to the 'good' test case with different format but fails the test with error message: panic: reflect: reflect.Value.Set using unaddressable value [recovered] . But when I try to remove the other field which is shown in the 'good too' test, it works.

The detailed error information:

=== RUN   TestGoodTest
--- PASS: TestGoodTest (0.00s)
=== RUN   TestGoodTooTest
--- PASS: TestGoodTooTest (0.00s)

=== RUN   TestBadTest
--- FAIL: TestBadTest (0.00s)
panic: reflect: reflect.Value.Set using unaddressable value [recovered]
    panic: reflect: reflect.Value.Set using unaddressable value

goroutine 8 [running]:
testing.tRunner.func1.2({0x963f80, 0xc00005caa0})
    D:/Go/src/testing/testing.go:1526 +0x24e
testing.tRunner.func1()
    D:/Go/src/testing/testing.go:1529 +0x39f
panic({0x963f80, 0xc00005caa0})
    D:/Go/src/runtime/panic.go:884 +0x213
reflect.flag.mustBeAssignableSlow(0x180?)
    D:/Go/src/reflect/value.go:262 +0x85
reflect.flag.mustBeAssignable(...)
    D:/Go/src/reflect/value.go:249
reflect.Value.Set({0x961700?, 0xc00007f098?, 0x0?}, {0x961700?, 0xc000008450?, 0xc000076d28?})
    D:/Go/src/reflect/value.go:2230 +0x6a
github.com/pelletier/go-toml/v2.(*decoder).unmarshalArray(0xc000024700?, 0xc00014c460, {0x961700?, 0xc00007f098?, 0x969b80?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:665 +0xe8
github.com/pelletier/go-toml/v2.(*decoder).handleValue(0xc000076ed8?, 0xc00014c460, {0x961700?, 0xc00007f098?, 0x3?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:655 +0xc5
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValueInner(0x96ff40?, {0x1, 0x0}, 0xc00000e3c0?, {0x961700?, 0xc00007f098?, 0x823d05?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1009 +0x8c
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValuePart(0xc000024700, {0x1, 0xc00014c428}, 0x195?, {0x96ff40?, 0xc00007f080?, 0xc00000a120?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1074 +0x905
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValueInner(0x96a420?, {0x1, 0xc00014c428}, 0x963f80?, {0x96ff40?, 0xc00007f080?, 0x96ff40?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1005 +0x71
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValuePart(0xc000024700, {0x1, 0xc00014c3f0}, 0x0?, {0x96a420?, 0xc00000a120?, 0xc000077348?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1047 +0x4d1
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValueInner(0x96e640?, {0x1, 0xc00014c3f0}, 0xc00000e398?, {0x96a420?, 0xc00000a120?, 0x82dc8a?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1005 +0x71
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValuePart(0xc000024700, {0x1, 0xc00014c3b8}, 0x96e640?, {0x96e640?, 0xc00000a120?, 0x199?})

    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1074 +0x905
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValuePart(0xc000024700, {0x1, 0xc00014c3b8}, 0x4?, {0x95e640?, 0xc00000a118?, 0x0?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1112 +0xb0b
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValueInner(0xc000024740?, {0x1, 0xc00014c3b8}, 0xc0000776e0?, {0x95e640?, 0xc00000a118?, 0xc00014c380?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:1005 +0x71
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValue(0xc000024700, 0xc00014c380, {0x95e640?, 0xc00000a118?, 0x893c76?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:991 +0xa5
github.com/pelletier/go-toml/v2.(*decoder).handleKeyValues(0xc000024700, {0x95e640?, 0xc00000a118?, 0x1f9821893f8?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:577 +0x151
github.com/pelletier/go-toml/v2.(*decoder).handleTable(0xc000067800?, {0x1, 0x0}, {0x95e640?, 0xc00000a118?, 0xc000068980?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:554 +0x193
github.com/pelletier/go-toml/v2.(*decoder).handleKeyPart(0xc000024700, {0x1, 0xc00013a5b0}, {0x969f40?, 0xc00000a110?, 0xc00007ea20?}, 0xc0000679d8, 0x998e68)
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:459 +0x4c3
github.com/pelletier/go-toml/v2.(*decoder).handleTablePart(0x0?, {0x50?, 0xc00013a5b0?}, {0x969f40?, 0xc00000a110?, 0x30?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:603 +0x4e
github.com/pelletier/go-toml/v2.(*decoder).handleTable(0x0?, {0x1, 0xc00013a5b0}, {0x969f40?, 0xc00000a110?, 0xc000067b01?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:550 +0x17b
github.com/pelletier/go-toml/v2.(*decoder).handleKeyPart(0xc000024700, {0x1, 0xc00013a578}, {0x96e6c0?, 0xc00000a110?, 0xc00005e4c0?}, 0xc000067c70, 0x998e68)
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:487 +0x81c
github.com/pelletier/go-toml/v2.(*decoder).handleTablePart(0x963f80?, {0xfe?, 0xc00013a578?}, {0x96e6c0?, 0xc00000a110?, 0xc00000e530?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:603 +0x4e
github.com/pelletier/go-toml/v2.(*decoder).handleTable(0xc000024718?, {0x1, 0xc00013a578}, {0x96e6c0?, 0xc00000a110?, 0x0?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:550 +0x17b
github.com/pelletier/go-toml/v2.(*decoder).handleRootExpression(0xc000024700, 0xc00013a540, {0x96e6c0?, 0xc00000a110?, 0xa9da80?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:262 +0x134
github.com/pelletier/go-toml/v2.(*decoder).fromParser(0xc000024700, {0x96e6c0?, 0xc00000a110?, 0x80?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:224 +0xaa
github.com/pelletier/go-toml/v2.(*decoder).FromParser(0xc000024700, {0x95e680?, 0xc00000a110?})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:209 +0x1e7
github.com/pelletier/go-toml/v2.(*Decoder).Decode(0xc000067f48, {0x95e680, 0xc00000a110})
    D:/gopath/pkg/mod/github.com/pelletier/go-toml/v2@v2.0.7/unmarshaler.go:113 +0x1a5
demoproject01/tomltest.TestBadTest(0xc000051a00)
    D:/workspace_goland/demoproject01/tomltest/tomltest_test.go:70 +0xea
testing.tRunner(0xc000051a00, 0x998dc8)
    D:/Go/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
    D:/Go/src/testing/testing.go:1629 +0x3ea

Process finished with the exit code 1

To Reproduce

package tomltest

import (
    "bytes"
    "testing"

    "github.com/pelletier/go-toml/v2"
)

type Pipeline struct {
    Mapping map[string]struct {
        Req [][]string `toml:"req"`
        Res [][]string `toml:"res"`
    } `toml:"mapping"`
}

type Pipelines struct {
    PipelineMapping map[string]*Pipeline `toml:"pipelines"`
}

var goodToml = `
[pipelines.register.mapping.inst]
req = [
    ["param1", "value1"],
]
res = [
    ["param2", "value2"],
]
`

var badToml = `
[pipelines.register]
mapping.inst.req = [
    ["param1", "value1"],
]
mapping.inst.res = [
    ["param2", "value2"],
]
`

var goodTooToml = `
[pipelines.register]
mapping.inst.req = [
    ["param1", "value1"],
]
`

func TestGoodTest(t *testing.T) {
    piplines := new(Pipelines)
    if err := toml.NewDecoder(bytes.NewBufferString(goodToml)).DisallowUnknownFields().Decode(piplines); err != nil {
        t.Fatal(err)
    }
    if piplines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
        t.Fatal("unmarshal failed with mismatch value")
    }
}

func TestGoodTooTest(t *testing.T) {
    piplines := new(Pipelines)
    if err := toml.NewDecoder(bytes.NewBufferString(goodTooToml)).DisallowUnknownFields().Decode(piplines); err != nil {
        t.Fatal(err)
    }
    if piplines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
        t.Fatal("unmarshal failed with mismatch value")
    }
}

func TestBadTest(t *testing.T) {
    piplines := new(Pipelines)
    if err := toml.NewDecoder(bytes.NewBufferString(badToml)).DisallowUnknownFields().Decode(piplines); err != nil {
        t.Fatal(err)
    }
    if piplines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
        t.Fatal("unmarshal failed with mismatch value")
    }
}

Expected behavior The 'bad' test case in the above should works as well as the other two.

Versions

pelletier commented 1 year ago

Thanks for your bug report! I've merged https://github.com/pelletier/go-toml/commit/986afffb7c67e7f95a55a5092f2a862cc26b5299, which should fix your issue. Feel free to reopen if you are still seeing the problem.