Skip to content

Commit

Permalink
encoding/json: fix panic unmarshaling into non-nil interface value
Browse files Browse the repository at this point in the history
Fixes #3614.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/6306051
  • Loading branch information
rsc committed Jun 7, 2012
1 parent 8022a1a commit 09b736a
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/pkg/encoding/json/decode.go
Expand Up @@ -273,9 +273,14 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (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() {
v = iv.Elem()
continue
e := iv.Elem()
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
v = e
continue
}
}

pv := v
Expand Down
46 changes: 46 additions & 0 deletions src/pkg/encoding/json/decode_test.go
Expand Up @@ -683,3 +683,49 @@ func TestEmptyString(t *testing.T) {
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)
}
}
}

0 comments on commit 09b736a

Please sign in to comment.