aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authorDaniel Martí <mvdan@mvdan.cc>2020-07-01 11:31:15 +0000
committerDaniel Martí <mvdan@mvdan.cc>2020-07-02 22:08:11 +0000
commit5de90d33c837af4d9a375a0a36811c7033655596 (patch)
treed034eb8de25b4c60e5db4741b159462af655fe32 /src/encoding
parenta4ba411b19fa0111a3c8fe059fcf5489d3bd6bbf (diff)
downloadgo-5de90d33c837af4d9a375a0a36811c7033655596.tar.gz
go-5de90d33c837af4d9a375a0a36811c7033655596.zip
Revert "encoding/json: don't reuse slice elements when decoding"
This reverts https://golang.org/cl/191783. Reason for revert: Broke too many programs which depended on the previous behavior, even when it was the opposite of what the documentation said. We can attempt to fix the original issue again for 1.16, while keeping those programs in mind. Fixes #39427. Change-Id: I7a7f24b2a594c597ef625aeff04fff29aaa88fc6 Reviewed-on: https://go-review.googlesource.com/c/go/+/240657 Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/json/decode.go40
-rw-r--r--src/encoding/json/decode_test.go15
2 files changed, 19 insertions, 36 deletions
diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go
index 20388cdc5b..86d8a69db7 100644
--- a/src/encoding/json/decode.go
+++ b/src/encoding/json/decode.go
@@ -177,7 +177,8 @@ func (d *decodeState) unmarshal(v interface{}) error {
d.scanWhile(scanSkipSpace)
// We decode rv not rv.Elem because the Unmarshaler interface
// test must be applied at the top level of the value.
- if err := d.value(rv); err != nil {
+ err := d.value(rv)
+ if err != nil {
return d.addErrorContext(err)
}
return d.savedError
@@ -507,7 +508,6 @@ func (d *decodeState) array(v reflect.Value) error {
return nil
}
v = pv
- initialSliceCap := 0
// Check type of target.
switch v.Kind() {
@@ -524,9 +524,8 @@ func (d *decodeState) array(v reflect.Value) error {
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
d.skip()
return nil
- case reflect.Slice:
- initialSliceCap = v.Cap()
- case reflect.Array:
+ case reflect.Array, reflect.Slice:
+ break
}
i := 0
@@ -537,6 +536,7 @@ func (d *decodeState) array(v reflect.Value) error {
break
}
+ // Get element of array, growing if necessary.
if v.Kind() == reflect.Slice {
// Grow slice if necessary
if i >= v.Cap() {
@@ -552,22 +552,19 @@ func (d *decodeState) array(v reflect.Value) error {
v.SetLen(i + 1)
}
}
- var into reflect.Value
+
if i < v.Len() {
- into = v.Index(i)
- if i < initialSliceCap {
- // Reusing an element from the slice's original
- // backing array; zero it before decoding.
- into.Set(reflect.Zero(v.Type().Elem()))
+ // Decode into element.
+ if err := d.value(v.Index(i)); err != nil {
+ return err
+ }
+ } else {
+ // Ran out of fixed array: skip.
+ if err := d.value(reflect.Value{}); err != nil {
+ return err
}
}
i++
- // Note that we decode the value even if we ran past the end of
- // the fixed array. In that case, we decode into an empty value
- // and do nothing with it.
- if err := d.value(into); err != nil {
- return err
- }
// Next token must be , or ].
if d.opcode == scanSkipSpace {
@@ -583,17 +580,16 @@ func (d *decodeState) array(v reflect.Value) error {
if i < v.Len() {
if v.Kind() == reflect.Array {
- // Zero the remaining elements.
- zero := reflect.Zero(v.Type().Elem())
+ // Array. Zero the rest.
+ z := reflect.Zero(v.Type().Elem())
for ; i < v.Len(); i++ {
- v.Index(i).Set(zero)
+ v.Index(i).Set(z)
}
} else {
v.SetLen(i)
}
}
- if v.Kind() == reflect.Slice && v.IsNil() {
- // Don't allow the resulting slice to be nil.
+ if i == 0 && v.Kind() == reflect.Slice {
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
}
return nil
diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go
index 2728c8ee50..219e845c7b 100644
--- a/src/encoding/json/decode_test.go
+++ b/src/encoding/json/decode_test.go
@@ -2099,10 +2099,7 @@ func TestSkipArrayObjects(t *testing.T) {
// slices, and arrays.
// Issues 4900 and 8837, among others.
func TestPrefilled(t *testing.T) {
- type T struct {
- A, B int
- }
- // Values here change, cannot reuse the table across runs.
+ // Values here change, cannot reuse table across runs.
var prefillTests = []struct {
in string
ptr interface{}
@@ -2138,16 +2135,6 @@ func TestPrefilled(t *testing.T) {
ptr: &[...]int{1, 2},
out: &[...]int{3, 0},
},
- {
- in: `[{"A": 3}]`,
- ptr: &[]T{{A: -1, B: -2}, {A: -3, B: -4}},
- out: &[]T{{A: 3}},
- },
- {
- in: `[{"A": 3}]`,
- ptr: &[...]T{{A: -1, B: -2}, {A: -3, B: -4}},
- out: &[...]T{{A: 3, B: -2}, {}},
- },
}
for _, tt := range prefillTests {