1
0
mirror of https://github.com/golang/go synced 2024-11-23 20:20:01 -07:00

encoding/gob: error out instead of panicking on nil dereference

Do not panic when we encounter nil interface values which are
invalid values for gob. Previously this wasn't caught yet
we were calling reflect.*.Type() on reflect.Invalid values
thereby causing panic:
  `panic: reflect: call of reflect.Value.Type on zero Value.`
which is a panic not enforced by encoding/gob itself.
We can catch this and send back an error to the caller.

Fixes #16204

Change-Id: Ie646796db297759a74a02eee5267713adbe0c3a0
Reviewed-on: https://go-review.googlesource.com/24989
Reviewed-by: Rob Pike <r@golang.org>
Run-TryBot: Rob Pike <r@golang.org>
This commit is contained in:
Emmanuel Odeke 2016-07-17 14:22:15 -07:00 committed by Rob Pike
parent 14e5951166
commit 0a2a64d85d
2 changed files with 17 additions and 0 deletions

View File

@ -215,6 +215,9 @@ func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
// guaranteeing that all necessary type information has been transmitted first. // guaranteeing that all necessary type information has been transmitted first.
// Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob. // Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob.
func (enc *Encoder) EncodeValue(value reflect.Value) error { func (enc *Encoder) EncodeValue(value reflect.Value) error {
if value.Kind() == reflect.Invalid {
return errors.New("gob: cannot encode nil value")
}
if value.Kind() == reflect.Ptr && value.IsNil() { if value.Kind() == reflect.Ptr && value.IsNil() {
panic("gob: cannot encode nil pointer of type " + value.Type().String()) panic("gob: cannot encode nil pointer of type " + value.Type().String())
} }

View File

@ -830,6 +830,20 @@ func TestPtrToMapOfMap(t *testing.T) {
} }
} }
// Test that untyped nils generate an error, not a panic.
// See Issue 16204.
func TestCatchInvalidNilValue(t *testing.T) {
encodeErr, panicErr := encodeAndRecover(nil)
if panicErr != nil {
t.Fatalf("panicErr=%v, should not panic encoding untyped nil", panicErr)
}
if encodeErr == nil {
t.Errorf("got err=nil, want non-nil error when encoding untyped nil value")
} else if !strings.Contains(encodeErr.Error(), "nil value") {
t.Errorf("expected 'nil value' error; got err=%v", encodeErr)
}
}
// A top-level nil pointer generates a panic with a helpful string-valued message. // A top-level nil pointer generates a panic with a helpful string-valued message.
func TestTopLevelNilPointer(t *testing.T) { func TestTopLevelNilPointer(t *testing.T) {
var ip *int var ip *int