mirror of
https://github.com/golang/go
synced 2024-11-15 11:20:30 -07:00
[release-branch.go1] encoding/json: fix panic unmarshaling into non-nil interface value
««« backport bee83c1509a3 encoding/json: fix panic unmarshaling into non-nil interface value Fixes #3614. R=golang-dev, adg CC=golang-dev https://golang.org/cl/6306051 »»»
This commit is contained in:
parent
cec2715018
commit
dc0f7d6fde
@ -273,9 +273,14 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
|
|||||||
_, isUnmarshaler = v.Interface().(Unmarshaler)
|
_, isUnmarshaler = v.Interface().(Unmarshaler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load value from interface, but only if the result will be
|
||||||
|
// usefully addressable.
|
||||||
if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
|
if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
|
||||||
v = iv.Elem()
|
e := iv.Elem()
|
||||||
continue
|
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||||
|
v = e
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pv := v
|
pv := v
|
||||||
|
@ -657,3 +657,49 @@ func TestEmptyString(t *testing.T) {
|
|||||||
t.Fatal("Decode: did not set Number1")
|
t.Fatal("Decode: did not set Number1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func intp(x int) *int {
|
||||||
|
p := new(int)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func intpp(x *int) **int {
|
||||||
|
pp := new(*int)
|
||||||
|
*pp = x
|
||||||
|
return pp
|
||||||
|
}
|
||||||
|
|
||||||
|
var interfaceSetTests = []struct {
|
||||||
|
pre interface{}
|
||||||
|
json string
|
||||||
|
post interface{}
|
||||||
|
}{
|
||||||
|
{"foo", `"bar"`, "bar"},
|
||||||
|
{"foo", `2`, 2.0},
|
||||||
|
{"foo", `true`, true},
|
||||||
|
{"foo", `null`, nil},
|
||||||
|
|
||||||
|
{nil, `null`, nil},
|
||||||
|
{new(int), `null`, nil},
|
||||||
|
{(*int)(nil), `null`, nil},
|
||||||
|
{new(*int), `null`, new(*int)},
|
||||||
|
{(**int)(nil), `null`, nil},
|
||||||
|
{intp(1), `null`, nil},
|
||||||
|
{intpp(nil), `null`, intpp(nil)},
|
||||||
|
{intpp(intp(1)), `null`, intpp(nil)},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterfaceSet(t *testing.T) {
|
||||||
|
for _, tt := range interfaceSetTests {
|
||||||
|
b := struct{ X interface{} }{tt.pre}
|
||||||
|
blob := `{"X":` + tt.json + `}`
|
||||||
|
if err := Unmarshal([]byte(blob), &b); err != nil {
|
||||||
|
t.Errorf("Unmarshal %#q: %v", blob, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(b.X, tt.post) {
|
||||||
|
t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user