]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: special-case panic message when returning Value{} from MakeFunc function
authorKeith Randall <khr@google.com>
Mon, 6 May 2019 19:58:54 +0000 (12:58 -0700)
committerKeith Randall <khr@golang.org>
Mon, 6 May 2019 21:23:29 +0000 (21:23 +0000)
Before this CL we used to panic with "nil pointer dereference" because
the value we're calling assignTo on is the zero Value. Provide a better
error message.

Fixes #28748

Change-Id: I7dd4c9e30b599863664d91e78cc45878d8b0052e
Reviewed-on: https://go-review.googlesource.com/c/go/+/175440
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/reflect/value.go
test/fixedbugs/issue28748.go [new file with mode: 0644]

index f0db43400951cf6f0d1981adb9ac06e3d731790d..c58b2d2567012ae2b90d6b97fd08f1e935ff8d15 100644 (file)
@@ -560,6 +560,10 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool) {
                }
                for i, typ := range ftyp.out() {
                        v := out[i]
+                       if v.typ == nil {
+                               panic("reflect: function created by MakeFunc using " + funcName(f) +
+                                       " returned zero Value")
+                       }
                        if v.flag&flagRO != 0 {
                                panic("reflect: function created by MakeFunc using " + funcName(f) +
                                        " returned value obtained from unexported field")
diff --git a/test/fixedbugs/issue28748.go b/test/fixedbugs/issue28748.go
new file mode 100644 (file)
index 0000000..4f9b022
--- /dev/null
@@ -0,0 +1,32 @@
+// run
+
+package main
+
+import (
+       "fmt"
+       "reflect"
+       "strings"
+)
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+func main() {
+       defer func() {
+               e := recover()
+               if e == nil {
+                       panic("should have panicked")
+               }
+               text := fmt.Sprintf("%s", e) // handles both string and runtime.errorString
+               if !strings.HasPrefix(text, "reflect:") {
+                       panic("wanted a reflect error, got this instead:\n" + text)
+               }
+       }()
+       r := reflect.MakeFunc(reflect.TypeOf(func() error { return nil }),
+               func(args []reflect.Value) []reflect.Value {
+                       var x [1]reflect.Value
+                       return x[:]
+               }).Interface().(func() error)
+       r()
+}