goccy / go-json

Fast JSON encoder/decoder compatible with encoding/json for Go
MIT License
3.11k stars 148 forks source link

[Bug] segmentation violation on nested structs with pointers #510

Open ryan-ju opened 6 months ago

ryan-ju commented 6 months ago

Version

v0.10.3

Example code

package main

import (
    "fmt"
    stdjson "encoding/json"
    "github.com/goccy/go-json"
)

type A struct {
    B *B `json:"b"`
}

type B struct {
    Foo *string `json:"foo"`
    Bar *string `json:"bar"`
}

func main() {
    str := "hello"

    v := A{
        B: &B{
            Foo: &str,
        },
    }

    bs, _ := stdjson.Marshal(v)
    fmt.Println(string(bs)) // Prints {"b":{"foo":"hello","bar":"hello"}}

    bs, _ = json.Marshal(v) // Panics
    fmt.Println(string(bs)) 
}

Console output

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xd pc=0xec25303]

goroutine 1 [running]:
github.com/goccy/go-json/internal/encoder/vm.ptrToString(...)
        /Users/ran/.gvm/pkgsets/go1.22.1/global/pkg/mod/github.com/goccy/go-json@v0.10.3/internal/encoder/vm/util.go:89
github.com/goccy/go-json/internal/encoder/vm.Run(0xc000108d00, {0xc000018400?, 0x0?, 0x0?}, 0xc00002bd88?)
        /Users/ran/.gvm/pkgsets/go1.22.1/global/pkg/mod/github.com/goccy/go-json@v0.10.3/internal/encoder/vm/vm.go:4580 +0x1efe3
github.com/goccy/go-json.encodeRunCode(0xc000108d00?, {0xc000018400?, 0xc00002bdd0?, 0xc0000300c0?}, 0xc000018800?)
        /Users/ran/.gvm/pkgsets/go1.22.1/global/pkg/mod/github.com/goccy/go-json@v0.10.3/encode.go:310 +0x56
github.com/goccy/go-json.encode(0xc000108d00, {0xec82040, 0xc000014090})
        /Users/ran/.gvm/pkgsets/go1.22.1/global/pkg/mod/github.com/goccy/go-json@v0.10.3/encode.go:235 +0x205
github.com/goccy/go-json.marshal({0xec82040, 0xc000014090}, {0x0, 0x0, 0x0?})
        /Users/ran/.gvm/pkgsets/go1.22.1/global/pkg/mod/github.com/goccy/go-json@v0.10.3/encode.go:150 +0xb9
github.com/goccy/go-json.MarshalWithOption(...)
        /Users/ran/.gvm/pkgsets/go1.22.1/global/pkg/mod/github.com/goccy/go-json@v0.10.3/json.go:185
github.com/goccy/go-json.Marshal({0xec82040?, 0xc000014090?})
        /Users/ran/.gvm/pkgsets/go1.22.1/global/pkg/mod/github.com/goccy/go-json@v0.10.3/json.go:170 +0x25
main.main()
        /Users/ran/Projects/xxx/tmp/main.go:109 +0xd7

go env

GO111MODULE='on'
GOARCH='amd64'
GOBIN=''
GOEXE=''
GOEXPERIMENT=''
GOFLAGS='-mod=mod'
GOHOSTARCH='amd64'
GOHOSTOS='darwin'
GOINSECURE=''
GOOS='darwin'
GOPROXY='https://goproxy.io,direct'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOVCS=''
GOVERSION='go1.22.1'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/sp/kyrr5gqs3z719c7lv933_cpr0000gn/T/go-build3263209783=/tmp/go-build -gno-record-gcc-switches -fno-common'
ryan-ju commented 6 months ago

This is a very serious bug, given how easy it is to reproduce

mei-rune commented 1 month ago

goroutine 222 gp=0xc000103180 m=4 mp=0xc000100008 [running]: runtime.throw({0x27b563d?, 0x27d9400?}) /usr/local/go/src/runtime/panic.go:1023 +0x5c fp=0xc005b61f48 sp=0xc005b61f18 pc=0xc44ffc runtime.sigpanic() /usr/local/go/src/runtime/signal_unix.go:895 +0x285 fp=0xc005b61fa8 sp=0xc005b61f48 pc=0xc5ee65 runtime.memmove() /usr/local/go/src/runtime/memmove_amd64.s:111 +0xb8 fp=0xc005b61fb0 sp=0xc005b61fa8 pc=0xc82bf8 github.com/goccy/go-json/internal/encoder.AppendMarshalJSON(0xc004d87040, 0xc00750ba78, {0xc0051d0000, 0x94c83, 0xac000}, {0x25fe180?, 0x24a19b0?}) /xxx/srcgithub.com/goccy/go-json/internal/encoder/encoder.go:437 +0x3c8 fp=0xc005b62128 sp=0xc005b61fb0 pc=0x1160c68 github.com/goccy/go-json/internal/encoder/vm.appendMarshalJSON(0x2779b60?, 0xc0051d0000?, {0xc0051d0000?, 0x0?, 0x1?}, {0x25fe180?, 0x24a19b0?}) /xxx/srcgithub.com/goccy/go-json/internal/encoder/vm/util.go:152 +0x25 fp=0xc005b62170 sp=0xc005b62128 pc=0x11e3a25 github.com/goccy/go-json/internal/encoder/vm.Run(0xc004d87040, {0xc002e26000?, 0x4?, 0xc000f00210?}, 0x1?) /xxx/srcgithub.com/goccy/go-json/internal/encoder/vm/vm.go:3945 +0x19547 fp=0xc005b644c8 sp=0xc005b62170 pc=0x11fd147 github.com/goccy/go-json.encodeRunCode(0xc004d87040?, {0xc002e26000?, 0x7f0f2820c5a8?, 0xc001e846d8?}, 0xca9f9d?) /xxx/srcgithub.com/goccy/go-json/encode.go:310 +0x56 fp=0xc005b64500 sp=0xc005b644c8 pc=0x120ad76 github.com/goccy/go-json.encode(0xc004d87040, {0x247bd40, 0xc001e846d8}) /xxx/srcgithub.com/goccy/go-json/encode.go:235 +0x205 fp=0xc005b64580 sp=0xc005b64500 pc=0x120a905 github.com/goccy/go-json.marshal({0x247bd40, 0xc001e846d8}, {0x0, 0x0, 0xc000bb8801?}) /xxx/srcgithub.com/goccy/go-json/encode.go:150 +0xb9 fp=0xc005b645e0 sp=0xc005b64580 pc=0x120a5f9 github.com/goccy/go-json.MarshalWithOption(...) /xxx/srcgithub.com/goccy/go-json/json.go:186 github.com/goccy/go-json.Marshal({0x247bd40?, 0xc001e846d8?}) /xxx/srcgithub.com/goccy/go-json/json.go:171 +0x25 fp=0xc005b64618 sp=0xc005b645e0 pc=0x120afc5 github.com/mei-rune/json.Marshal(...)