Skip to content
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/gob: panic on encoding nil pointer #3704

Closed
dsymonds opened this issue Jun 5, 2012 · 9 comments
Closed

encoding/gob: panic on encoding nil pointer #3704

dsymonds opened this issue Jun 5, 2012 · 9 comments

Comments

@dsymonds
Copy link
Contributor

dsymonds commented Jun 5, 2012

With this code,

----------
package main

import (
    "bytes"
    "encoding/gob"
    "fmt"
)

type T struct{ N int }

func main() {
    var t *T
    buf := new(bytes.Buffer)
    if err := gob.NewEncoder(buf).Encode(t); err != nil {
        fmt.Printf("Failed: %v\n", err)
    }
}
----------

I get this panic in the playground:

----------
panic: reflect: call of reflect.Value.Type on zero Value [recovered]
    panic: reflect: call of reflect.Value.Type on zero Value

goroutine 1 [running]:
encoding/gob.catchError(0xf840053090, 0x2b0699b14100)
    go/src/pkg/encoding/gob/error.go:38 +0x9a
----- stack segment boundary -----
reflect.Value.Type(0x0, 0x0, 0x0, 0x0, 0x0, ...)
    go/src/pkg/reflect/value.go:1425 +0x78
encoding/gob.(*Encoder).encode(0xf840053000, 0xf840053030, 0x0, 0x0, 0x0, ...)
    go/src/pkg/encoding/gob/encode.go:726 +0x112
encoding/gob.(*Encoder).EncodeValue(0xf840053000, 0x4676f0, 0x0, 0x160, 0x0, ...)
    go/src/pkg/encoding/gob/encoder.go:246 +0x2a4
encoding/gob.(*Encoder).Encode(0xf840053000, 0x4676e0, 0x0, 0x0, 0xf840049000, ...)
    go/src/pkg/encoding/gob/encoder.go:177 +0x5f
main.main()
    /tmpfs/gosandbox-b32668d5_3d9b71df_7f3d3179_0c1e92f2_4e9ea712/prog.go:14 +0x9b
----------

It breaks in the same way at near-tip.
@robpike
Copy link
Contributor

robpike commented Jun 5, 2012

Comment 1:

What would you have it do? It can't send anything.

@dsymonds
Copy link
Contributor Author

dsymonds commented Jun 5, 2012

Comment 2:

I don't know what it should do, but not panicking would be a good start.
I actually came across this while encoding a struct with a []interface{}
field that had a nil pointer in amongst stuff like non-empty strings. Isn't
that a reasonable data structure for gob to be able to encode/decode?

@robpike
Copy link
Contributor

robpike commented Jun 5, 2012

Comment 3:

I think a panic is the right thing to do. It could return an error but there's nothing
to do if the error occurs because nothing is sent, and that will violate the wire
protocol.
Consider this code:
enc.Encode(x)
enc.Encode(y)
You should always check errors, of course, and something else could go wrong, but it's
reasonable to consider that in a working, debugged program this transmission can always
be decoded by doing, on the remote side,
dec.Decode(&x)
dec.Decode(&y)
The thing is, if x and y are both of type *T, no message will be sent for that pointer,
and the value of y will be decoded into x.
In short, attempting to send a top-level nil is a pretty serious violation of the
streaming protocol. Of course, it's trivial to return an error and expect the user to
check for error, and I could be talked into that, but I want to be clear that you cannot
send a top-level nil ever. The gob package is not at fault here; the client is
misbehaving.

@rsc
Copy link
Contributor

rsc commented Jun 5, 2012

Comment 4:

I wrote via email but it hasn't shown up yet:
I don't believe it is. gob doesn't know what a pointer is: everything gets flattened.
Putting a nil pointer in an interface{} value creates a non-zero value (it's not the nil
interface) that gob cannot send (it can't express 'nil pointer').

@rsc
Copy link
Contributor

rsc commented Jun 5, 2012

Comment 5:

"I don't believe it is" is a response to comment #2. One of code.google.com's many
excellent features is that you cannot include quoted text.

@rsc
Copy link
Contributor

rsc commented Jun 5, 2012

Comment 6:

I don't believe it is. gob doesn't know what a pointer is: everything
gets flattened.
Putting a nil pointer in an interface{} value creates a non-zero value
(it's not the
nil interface) that gob cannot send (it can't express 'nil pointer').
Russ

@robpike
Copy link
Contributor

robpike commented Jun 5, 2012

Comment 7:

Correct. An interface value can be transmitted only if the concrete value itself is
transmittable. At least for now, that's equivalent to saying that interfaces holding
typed nil pointers cannot be sent.
I can try to make the panic more descriptive, but actually "fixing" this is a
significant design change.

@dsymonds
Copy link
Contributor Author

dsymonds commented Jun 6, 2012

Comment 8:

Can at least a non-top-level nil pointer result in an error instead of a
panic?

@robpike
Copy link
Contributor

robpike commented Jun 12, 2012

Comment 9:

This issue was closed by revision ea3c3bb.

Status changed to Fixed.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
@rsc rsc unassigned robpike Jun 22, 2022
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants