-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
encoding/json: panic when unmarshalling to struct with embedded struct pointer #30489
Comments
The root cause of this is #30148. Closing as duplicate. |
Wow. I understand the difficulty here, but just closing (and presumably ignoring - forgive me if there's a process I don't understand here) seems to be ignoring a big issue. The whole idea of unmarshallers (and marshallers https://play.golang.org/p/KsYZvfY7kvk) seems to be a little broken with embedding. The "spooky action at a distance" is very unsettling here. I generated some easyjson marshallers for core structs, then found much later on that this broke unrelated code that happened to embed these structs. This means I can never implement an unmarshaller on any public struct in case someone somewhere has embedded it and things will start crashing Cheeky little /cc @rsc |
Perhaps, but not one specific to |
I would say the opposite is true. Users should never embed a type that they do not own because it is unreasonable to expect that the author of the type never adds new fields and methods. Of course, people do this anyways and are surprised when their code breaks. Hence, the brittleness of embedding. FYI, the Go1 compatibility calls this out:
|
Ok. This is not something I was previously aware of! My bad for thinking I
know what I'm doing. I thought embedding was supposed to be one of the
strengths of the language -'composition over inheritance' and all that.
Will watch for it carefully in future
…On Fri, 1 Mar 2019, 12:13 am Joe Tsai, ***@***.***> wrote:
This means I can never implement an unmarshaller on any public struct in
case someone somewhere has embedded it and things will start crashing
I would say the opposite is true. Users should never embed a type that
they do not own because it is unreasonable to expect that the author of the
type never adds new fields and methods.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#30489 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAb33GLDc9r5tpDSTSTU3TVwHpH3ACSxks5vSHCTgaJpZM4bX-WO>
.
|
What version of Go are you using (
go version
)?1.12
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
https://play.golang.org/p/SZeGjpJFpDr
What did you expect to see?
Certainly no panic. Ideally the struct would be fully populated from the json
What did you see instead?
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0x107ad2]
goroutine 1 [running]:
main.(*A).UnmarshalJSON(0x0, 0x45a000, 0x1c, 0x1c, 0x0, 0x0)
/tmp/sandbox606414898/main.go:17 +0x12
encoding/json.(*decodeState).object(0x454060, 0x1242c0, 0x40a0e0, 0x16, 0x454078, 0x207b)
/usr/local/go/src/encoding/json/decode.go:611 +0x2920
encoding/json.(*decodeState).value(0x454060, 0x1242c0, 0x40a0e0, 0x16, 0x454078, 0x22)
/usr/local/go/src/encoding/json/decode.go:381 +0x60
encoding/json.(*decodeState).unmarshal(0x454060, 0x1242c0, 0x40a0e0, 0x454078, 0x0, 0x0)
/usr/local/go/src/encoding/json/decode.go:179 +0x240
encoding/json.Unmarshal(0x45a000, 0x1c, 0x1c, 0x1242c0, 0x40a0e0, 0x20af, 0x8, 0x1250a0)
/usr/local/go/src/encoding/json/decode.go:106 +0x180
main.main()
/tmp/sandbox606414898/main.go:23 +0xc0
Looks like the code sees that c is non-null and implements Unmarshaller, so calls UnmarshalJSON with c.A as the receiver. Unfortunately c.A is nil. Ideally the library would detect that c does not implement Unmarshaller itself and carry on with standard decoding.
The big problem here is that you can have working code, then implement a working unmarshaller on a struct and then find the code as a whole breaks. I found this after generating some easyjson unmarshallers for a subset of the structs in our codebase.
Note similarity to #22967
The text was updated successfully, but these errors were encountered: