json-iterator / go

A high-performance 100% compatible drop-in replacement of "encoding/json"
http://jsoniter.com/migrate-from-go-std.html
MIT License
13.33k stars 1.02k forks source link

BUG: Parsing structure stack overflow for loop references #696

Open clearcodecn opened 5 months ago

clearcodecn commented 5 months ago

follow code cause stack overflow


import (
    "fmt"
    jsoniter "github.com/json-iterator/go"
    "testing"
)

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

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

func TestJSON(t *testing.T) {
    var a = A{}
    var b = B{}
    a.B = &b
    b.A = &a

    var ji = jsoniter.ConfigCompatibleWithStandardLibrary
    data, _ := ji.Marshal(a)
    fmt.Println(string(data))
}

output:


runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0x140206c03b0 stack=[0x140206c0000, 0x140406c0000]
fatal error: stack overflow

runtime stack:
runtime.throw({0x1050e5fbb?, 0x105aa7f00?})
    /usr/local/go/src/runtime/panic.go:1047 +0x40 fp=0x16ff2ad50 sp=0x16ff2ad20 pc=0x10476af30
runtime.newstack()
    /usr/local/go/src/runtime/stack.go:1105 +0x468 fp=0x16ff2af00 sp=0x16ff2ad50 pc=0x104785bb8
runtime.morestack()
    /usr/local/go/src/runtime/asm_arm64.s:316 +0x70 fp=0x16ff2af00 sp=0x16ff2af00 pc=0x10479fd10

...

but official package can handle this issue normally code:

import (
    gojson "encoding/json"
    "fmt"
    "testing"
)

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

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

func TestJSON(t *testing.T) {
    var a = A{}
    var b = B{}
    a.B = &b
    b.A = &a

    data, _ := gojson.Marshal(a)
    fmt.Println(string(data))
}

out:

=== RUN   TestJSON

--- PASS: TestJSON (0.00s)
PASS