go-json icon indicating copy to clipboard operation
go-json copied to clipboard

Compiler SIGSEGV on embedding of a struct with a recursive field named via struct tag

Open jpicht opened this issue 1 year ago • 1 comments

Thanks for the great library!

I ran into a little issue today. With the test case below the compiler fails with a nil pointer de-reference:

=== RUN   TestBrokenRecursion
--- FAIL: TestBrokenRecursion (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x60 pc=0x5608a7]

goroutine 6 [running]:
testing.tRunner.func1.2({0x805500, 0xb9eb50})
	/usr/local/go/src/testing/testing.go:1545 +0x238
testing.tRunner.func1()
	/usr/local/go/src/testing/testing.go:1548 +0x397
panic({0x805500?, 0xb9eb50?})
	/usr/local/go/src/runtime/panic.go:914 +0x21f
github.com/goccy/go-json/internal/encoder.copyOpcode(0x0)
	/.../go-json/internal/encoder/opcode.go:324 +0x27
github.com/goccy/go-json/internal/encoder.(*Compiler).linkRecursiveCode(0xc0000ab890?, 0xc0000aba70)
	/.../go-json/internal/encoder/compiler.go:908 +0x185
github.com/goccy/go-json/internal/encoder.(*Compiler).codeToOpcode(0xc0000f1ce0?, 0xc0000aba70, 0x7dbd00, {0x931488?, 0xc0000ab890?})
	/.../go-json/internal/encoder/compiler.go:894 +0xe5
github.com/goccy/go-json/internal/encoder.(*Compiler).codeToOpcodeSet(0x40ec45?, 0x7dbd00, {0x931488?, 0xc0000ab890})
	/.../go-json/internal/encoder/compiler.go:108 +0xd8
github.com/goccy/go-json/internal/encoder.(*Compiler).compile(0xc00006c598?, 0x7dbd00)
	/.../go-json/internal/encoder/compiler.go:104 +0x4d
github.com/goccy/go-json/internal/encoder.CompileToGetCodeSet(0xc00006c670?, 0x477645?)
	/.../go-json/internal/encoder/compiler_norace.go:22 +0x145
github.com/goccy/go-json.encode(0xc0000ad2b0, {0x7dbd00, 0xc00006e1e8})
	/.../go-json/encode.go:226 +0xae
github.com/goccy/go-json.marshal({0x7dbd00, 0xc00006e1e8}, {0x0, 0x0, 0x4ed801?})
	/.../go-json/encode.go:150 +0xb9
github.com/goccy/go-json.MarshalWithOption(...)
	/.../go-json/json.go:186
github.com/goccy/go-json.Marshal({0x7dbd00?, 0xc00006e1e8?})
	/.../go-json/json.go:171 +0x25
github.com/goccy/go-json_test.TestBrokenRecursion(0xc0000f6340)
	/.../go-json/recursion_test.go:10 +0x2e
testing.tRunner(0xc0000f6340, 0x8b1f00)
	/usr/local/go/src/testing/testing.go:1595 +0xff
created by testing.(*T).Run in goroutine 1
	/usr/local/go/src/testing/testing.go:1648 +0x3ad
exit status 2
FAIL	github.com/goccy/go-json	0.007s

In the case below ctx.structTypeToCodes[typeptr] is unset in Compiler.linkRecursiveCode when trying to link json_test.Inner. ctx.structTypeToCodes only contains json_test.Outer at this point.

Minimized test case

package json_test

import (
	"testing"

	"github.com/goccy/go-json"
)

func TestBrokenRecursion(t *testing.T) {
	_, err := json.Marshal(&Outer{})
	if err != nil {
		t.Fail()
	}
}

type Outer struct {
	*Inner
}

type Inner struct {
	Inner *Inner `json:"inner"`
}

jpicht avatar Aug 30 '23 19:08 jpicht

Possible duplicate of #459

NgoKimPhu avatar Nov 04 '23 03:11 NgoKimPhu