Describe the bug
We encountered a fatal panic when using go-json to marshal a struct that had previously been populated by unmarshaling from an HTTP response stream. The panic occurs in the string encoding logic.
Environment
-
Go Version: go1.25.3
-
go-json Version: v0.10.5
To Reproduce
-
Define a complex nested struct (with generics, e.g., SearchResponse[T]).
-
Use json.NewDecoder(resp.Body).Decode(&v) to unmarshal data directly from an io.ReadCloser (HTTP response body).
-
Later, attempt to marshal the populated struct (or a struct containing it) using json.MarshalIndent.
-
The panic occurs randomly under certain data conditions.
Expected behavior
The library should safely marshal the data without panicking, regardless of the source of the unmarshaled data.
Stack Trace
unexpected fault address 0x0
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x80 addr=0x0 pc=0x7898ff]
goroutine 40 [running]:
runtime.throw(...)
/path/to/go/src/runtime/panic.go:1094
runtime.sigpanic()
/path/to/go/src/runtime/signal_unix.go:939
github.com/goccy/go-json/internal/encoder.appendNormalizedHTMLString({0xc0005bc000?, 0x0?, 0x119?}, {0x6530313031383634, 0x63342d663164372d})
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/internal/encoder/string.go:73 +0xdff
github.com/goccy/go-json/internal/encoder.AppendString(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/internal/encoder/string.go:52
github.com/goccy/go-json/internal/encoder/vm_indent.Run(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/internal/encoder/vm_indent/vm.go:1751
github.com/goccy/go-json.encodeRunIndentCode(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/encode.go:325
github.com/goccy/go-json.encodeIndent(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/encode.go:288
github.com/goccy/go-json.marshalIndent(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/encode.go:201
github.com/goccy/go-json.MarshalIndent(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/json.go:192
gitee.com/mstes/base-framework/logger.(*SyncLogger).sync(...)
/path/to/project/vendor/gitee.com/mstes/base-framework/logger/sync.go:56
... (truncated for brevity) ...
Additional context
We suspect this might be related to how the decoder handles memory when reading from a stream. It appears that a string reference might be pointing to a buffer that has been reused or garbage collected by the time the marshaling phase runs.
Workaround
We have temporarily switched to using the standard library encoding/json for the unmarshaling step, which resolves the issue.
We encountered a fatal panic when using go-json to marshal a struct that had previously been populated by unmarshaling from an HTTP response stream. The panic occurs in the string encoding logic.
Environment
Go Version: go1.25.3
go-json Version: v0.10.5
To Reproduce
Define a complex nested struct (with generics, e.g., SearchResponse[T]).
Use json.NewDecoder(resp.Body).Decode(&v) to unmarshal data directly from an io.ReadCloser (HTTP response body).
Later, attempt to marshal the populated struct (or a struct containing it) using json.MarshalIndent.
The panic occurs randomly under certain data conditions.
Expected behavior
The library should safely marshal the data without panicking, regardless of the source of the unmarshaled data.
Stack Trace
unexpected fault address 0x0
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x80 addr=0x0 pc=0x7898ff]
goroutine 40 [running]:
runtime.throw(...)
/path/to/go/src/runtime/panic.go:1094
runtime.sigpanic()
/path/to/go/src/runtime/signal_unix.go:939
github.com/goccy/go-json/internal/encoder.appendNormalizedHTMLString({0xc0005bc000?, 0x0?, 0x119?}, {0x6530313031383634, 0x63342d663164372d})
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/internal/encoder/string.go:73 +0xdff
github.com/goccy/go-json/internal/encoder.AppendString(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/internal/encoder/string.go:52
github.com/goccy/go-json/internal/encoder/vm_indent.Run(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/internal/encoder/vm_indent/vm.go:1751
github.com/goccy/go-json.encodeRunIndentCode(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/encode.go:325
github.com/goccy/go-json.encodeIndent(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/encode.go:288
github.com/goccy/go-json.marshalIndent(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/encode.go:201
github.com/goccy/go-json.MarshalIndent(...)
/path/to/project/vendor/github.com/goccy/go-json@v0.10.5/json.go:192
gitee.com/mstes/base-framework/logger.(*SyncLogger).sync(...)
/path/to/project/vendor/gitee.com/mstes/base-framework/logger/sync.go:56
... (truncated for brevity) ...
Additional context
We suspect this might be related to how the decoder handles memory when reading from a stream. It appears that a string reference might be pointing to a buffer that has been reused or garbage collected by the time the marshaling phase runs.
Workaround
We have temporarily switched to using the standard library encoding/json for the unmarshaling step, which resolves the issue.