aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2018-10-15 17:09:34 -0400
committerFilippo Valsorda <filippo@golang.org>2018-10-15 17:09:34 -0400
commit623650b27aa42dd2ccd20fc4a79f8fe7b8559987 (patch)
treebfafa16d1bfd57fc1d9831c22e6e236be3d52281 /src/encoding
parent36c789b1fd72af5ff6e756794597a3a85e069998 (diff)
parent1961d8d72a53e780effa18bfa8dbe4e4282df0b2 (diff)
downloadgo-623650b27aa42dd2ccd20fc4a79f8fe7b8559987.tar.xz
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: I218ba1b89a2df6e4335c6a5846889d9a04affe5d
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/base32/base32_test.go10
-rw-r--r--src/encoding/base64/base64_test.go8
-rw-r--r--src/encoding/json/decode.go133
-rw-r--r--src/encoding/json/decode_test.go19
4 files changed, 81 insertions, 89 deletions
diff --git a/src/encoding/base32/base32_test.go b/src/encoding/base32/base32_test.go
index c5506ed4de..b74054ba40 100644
--- a/src/encoding/base32/base32_test.go
+++ b/src/encoding/base32/base32_test.go
@@ -425,7 +425,7 @@ IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF
NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42
LNEBUWIIDFON2CA3DBMJXXE5LNFY==
====`
- encodedShort := strings.Replace(encoded, "\n", "", -1)
+ encodedShort := strings.ReplaceAll(encoded, "\n", "")
dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
res1, err := ioutil.ReadAll(dec)
@@ -465,7 +465,7 @@ func TestWithCustomPadding(t *testing.T) {
for _, testcase := range pairs {
defaultPadding := StdEncoding.EncodeToString([]byte(testcase.decoded))
customPadding := StdEncoding.WithPadding('@').EncodeToString([]byte(testcase.decoded))
- expected := strings.Replace(defaultPadding, "=", "@", -1)
+ expected := strings.ReplaceAll(defaultPadding, "=", "@")
if expected != customPadding {
t.Errorf("Expected custom %s, got %s", expected, customPadding)
@@ -675,7 +675,7 @@ func TestWithoutPaddingClose(t *testing.T) {
expected := testpair.encoded
if encoding.padChar == NoPadding {
- expected = strings.Replace(expected, "=", "", -1)
+ expected = strings.ReplaceAll(expected, "=", "")
}
res := buf.String()
@@ -697,7 +697,7 @@ func TestDecodeReadAll(t *testing.T) {
for encIndex, encoding := range encodings {
encoded := pair.encoded
if encoding.padChar == NoPadding {
- encoded = strings.Replace(encoded, "=", "", -1)
+ encoded = strings.ReplaceAll(encoded, "=", "")
}
decReader, err := ioutil.ReadAll(NewDecoder(encoding, strings.NewReader(encoded)))
@@ -723,7 +723,7 @@ func TestDecodeSmallBuffer(t *testing.T) {
for encIndex, encoding := range encodings {
encoded := pair.encoded
if encoding.padChar == NoPadding {
- encoded = strings.Replace(encoded, "=", "", -1)
+ encoded = strings.ReplaceAll(encoded, "=", "")
}
decoder := NewDecoder(encoding, strings.NewReader(encoded))
diff --git a/src/encoding/base64/base64_test.go b/src/encoding/base64/base64_test.go
index f019654f5b..f7f312ca39 100644
--- a/src/encoding/base64/base64_test.go
+++ b/src/encoding/base64/base64_test.go
@@ -53,8 +53,8 @@ func stdRef(ref string) string {
// Convert a reference string to URL-encoding
func urlRef(ref string) string {
- ref = strings.Replace(ref, "+", "-", -1)
- ref = strings.Replace(ref, "/", "_", -1)
+ ref = strings.ReplaceAll(ref, "+", "-")
+ ref = strings.ReplaceAll(ref, "/", "_")
return ref
}
@@ -72,7 +72,7 @@ func rawURLRef(ref string) string {
var funnyEncoding = NewEncoding(encodeStd).WithPadding(rune('@'))
func funnyRef(ref string) string {
- return strings.Replace(ref, "=", "@", -1)
+ return strings.ReplaceAll(ref, "=", "@")
}
type encodingTest struct {
@@ -418,7 +418,7 @@ j+mSARB/17pKVXYWHXjsj7yIex0PadzXMO1zT5KHoNA3HT8ietoGhgjsfA+CSnvvqh/jJtqsrwOv
2b6NGNzXfTYexzJ+nU7/ALkf4P8Awv6P9KvTQQ4AgyDqCF85Pho3CTB7eHwXoH+LT65uZbX9X+o2
bqbPb06551Y4
`
- encodedShort := strings.Replace(encoded, "\n", "", -1)
+ encodedShort := strings.ReplaceAll(encoded, "\n", "")
dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
res1, err := ioutil.ReadAll(dec)
diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go
index 82dc78083a..cab4616ba3 100644
--- a/src/encoding/json/decode.go
+++ b/src/encoding/json/decode.go
@@ -11,7 +11,6 @@ import (
"bytes"
"encoding"
"encoding/base64"
- "errors"
"fmt"
"reflect"
"strconv"
@@ -280,10 +279,10 @@ func (d *decodeState) readIndex() int {
return d.off - 1
}
-// errPhase is used for errors that should not happen unless
-// there is a bug in the JSON decoder or something is editing
-// the data slice while the decoder executes.
-var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?")
+// phasePanicMsg is used as a panic message when we end up with something that
+// shouldn't happen. It can indicate a bug in the JSON decoder, or that
+// something is editing the data slice while the decoder executes.
+const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
func (d *decodeState) init(data []byte) *decodeState {
d.data = data
@@ -365,7 +364,7 @@ func (d *decodeState) scanWhile(op int) {
func (d *decodeState) value(v reflect.Value) error {
switch d.opcode {
default:
- return errPhase
+ panic(phasePanicMsg)
case scanBeginArray:
if v.IsValid() {
@@ -407,26 +406,23 @@ type unquotedValue struct{}
// quoted string literal or literal null into an interface value.
// If it finds anything other than a quoted string literal or null,
// valueQuoted returns unquotedValue{}.
-func (d *decodeState) valueQuoted() (interface{}, error) {
+func (d *decodeState) valueQuoted() interface{} {
switch d.opcode {
default:
- return nil, errPhase
+ panic(phasePanicMsg)
case scanBeginArray, scanBeginObject:
d.skip()
d.scanNext()
case scanBeginLiteral:
- v, err := d.literalInterface()
- if err != nil {
- return nil, err
- }
+ v := d.literalInterface()
switch v.(type) {
case nil, string:
- return v, nil
+ return v
}
}
- return unquotedValue{}, nil
+ return unquotedValue{}
}
// indirect walks down v allocating pointers as needed,
@@ -520,10 +516,7 @@ func (d *decodeState) array(v reflect.Value) error {
case reflect.Interface:
if v.NumMethod() == 0 {
// Decoding into nil interface? Switch to non-reflect code.
- ai, err := d.arrayInterface()
- if err != nil {
- return err
- }
+ ai := d.arrayInterface()
v.Set(reflect.ValueOf(ai))
return nil
}
@@ -533,8 +526,7 @@ 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.Array:
- case reflect.Slice:
+ case reflect.Array, reflect.Slice:
break
}
@@ -584,7 +576,7 @@ func (d *decodeState) array(v reflect.Value) error {
break
}
if d.opcode != scanArrayValue {
- return errPhase
+ panic(phasePanicMsg)
}
}
@@ -628,10 +620,7 @@ func (d *decodeState) object(v reflect.Value) error {
// Decoding into nil interface? Switch to non-reflect code.
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
- oi, err := d.objectInterface()
- if err != nil {
- return err
- }
+ oi := d.objectInterface()
v.Set(reflect.ValueOf(oi))
return nil
}
@@ -680,7 +669,7 @@ func (d *decodeState) object(v reflect.Value) error {
break
}
if d.opcode != scanBeginLiteral {
- return errPhase
+ panic(phasePanicMsg)
}
// Read key.
@@ -689,7 +678,7 @@ func (d *decodeState) object(v reflect.Value) error {
item := d.data[start:d.readIndex()]
key, ok := unquoteBytes(item)
if !ok {
- return errPhase
+ panic(phasePanicMsg)
}
// Figure out field corresponding to key.
@@ -753,16 +742,12 @@ func (d *decodeState) object(v reflect.Value) error {
d.scanWhile(scanSkipSpace)
}
if d.opcode != scanObjectKey {
- return errPhase
+ panic(phasePanicMsg)
}
d.scanWhile(scanSkipSpace)
if destring {
- q, err := d.valueQuoted()
- if err != nil {
- return err
- }
- switch qv := q.(type) {
+ switch qv := d.valueQuoted().(type) {
case nil:
if err := d.literalStore(nullLiteral, subv, false); err != nil {
return err
@@ -827,7 +812,7 @@ func (d *decodeState) object(v reflect.Value) error {
break
}
if d.opcode != scanObjectValue {
- return errPhase
+ panic(phasePanicMsg)
}
d.errorContext = originalErrorContext
@@ -871,18 +856,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if item[0] != '"' {
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- var val string
- switch item[0] {
- case 'n':
- val = "null"
- case 't', 'f':
- val = "bool"
- default:
- val = "number"
- }
- d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
+ return nil
+ }
+ val := "number"
+ switch item[0] {
+ case 'n':
+ val = "null"
+ case 't', 'f':
+ val = "bool"
}
+ d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
return nil
}
s, ok := unquoteBytes(item)
@@ -890,7 +873,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
return ut.UnmarshalText(s)
}
@@ -941,7 +924,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
switch v.Kind() {
default:
@@ -973,7 +956,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
s := string(item)
switch v.Kind() {
@@ -1034,24 +1017,24 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
// but they avoid the weight of reflection in this common case.
// valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() (val interface{}, err error) {
+func (d *decodeState) valueInterface() (val interface{}) {
switch d.opcode {
default:
- err = errPhase
+ panic(phasePanicMsg)
case scanBeginArray:
- val, err = d.arrayInterface()
+ val = d.arrayInterface()
d.scanNext()
case scanBeginObject:
- val, err = d.objectInterface()
+ val = d.objectInterface()
d.scanNext()
case scanBeginLiteral:
- val, err = d.literalInterface()
+ val = d.literalInterface()
}
return
}
// arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() ([]interface{}, error) {
+func (d *decodeState) arrayInterface() []interface{} {
var v = make([]interface{}, 0)
for {
// Look ahead for ] - can only happen on first iteration.
@@ -1060,11 +1043,7 @@ func (d *decodeState) arrayInterface() ([]interface{}, error) {
break
}
- vi, err := d.valueInterface()
- if err != nil {
- return nil, err
- }
- v = append(v, vi)
+ v = append(v, d.valueInterface())
// Next token must be , or ].
if d.opcode == scanSkipSpace {
@@ -1074,14 +1053,14 @@ func (d *decodeState) arrayInterface() ([]interface{}, error) {
break
}
if d.opcode != scanArrayValue {
- return nil, errPhase
+ panic(phasePanicMsg)
}
}
- return v, nil
+ return v
}
// objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() (map[string]interface{}, error) {
+func (d *decodeState) objectInterface() map[string]interface{} {
m := make(map[string]interface{})
for {
// Read opening " of string key or closing }.
@@ -1091,7 +1070,7 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
break
}
if d.opcode != scanBeginLiteral {
- return nil, errPhase
+ panic(phasePanicMsg)
}
// Read string key.
@@ -1100,7 +1079,7 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
item := d.data[start:d.readIndex()]
key, ok := unquote(item)
if !ok {
- return nil, errPhase
+ panic(phasePanicMsg)
}
// Read : before value.
@@ -1108,16 +1087,12 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
d.scanWhile(scanSkipSpace)
}
if d.opcode != scanObjectKey {
- return nil, errPhase
+ panic(phasePanicMsg)
}
d.scanWhile(scanSkipSpace)
// Read value.
- vi, err := d.valueInterface()
- if err != nil {
- return nil, err
- }
- m[key] = vi
+ m[key] = d.valueInterface()
// Next token must be , or }.
if d.opcode == scanSkipSpace {
@@ -1127,16 +1102,16 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
break
}
if d.opcode != scanObjectValue {
- return nil, errPhase
+ panic(phasePanicMsg)
}
}
- return m, nil
+ return m
}
// literalInterface consumes and returns a literal from d.data[d.off-1:] and
// it reads the following byte ahead. The first byte of the literal has been
// read already (that's how the caller knows it's a literal).
-func (d *decodeState) literalInterface() (interface{}, error) {
+func (d *decodeState) literalInterface() interface{} {
// All bytes inside literal return scanContinue op code.
start := d.readIndex()
d.scanWhile(scanContinue)
@@ -1145,27 +1120,27 @@ func (d *decodeState) literalInterface() (interface{}, error) {
switch c := item[0]; c {
case 'n': // null
- return nil, nil
+ return nil
case 't', 'f': // true, false
- return c == 't', nil
+ return c == 't'
case '"': // string
s, ok := unquote(item)
if !ok {
- return nil, errPhase
+ panic(phasePanicMsg)
}
- return s, nil
+ return s
default: // number
if c != '-' && (c < '0' || c > '9') {
- return nil, errPhase
+ panic(phasePanicMsg)
}
n, err := d.convertNumber(string(item))
if err != nil {
d.saveError(err)
}
- return n, nil
+ return n
}
}
diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go
index defa97e40f..5fbe67a706 100644
--- a/src/encoding/json/decode_test.go
+++ b/src/encoding/json/decode_test.go
@@ -445,6 +445,7 @@ var unmarshalTests = []unmarshalTest{
{in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
{in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
{in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
+ {in: `[2, 3`, err: &SyntaxError{msg: "unexpected end of JSON input", Offset: 5}},
// raw value errors
{in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
@@ -460,6 +461,7 @@ var unmarshalTests = []unmarshalTest{
{in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
{in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
{in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
+ {in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")},
// empty array to interface test
{in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
@@ -826,6 +828,7 @@ var unmarshalTests = []unmarshalTest{
{in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)},
{in: `{"B": "null"}`, ptr: new(B), out: B{false}},
{in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)},
+ {in: `{"B": [2, 3]}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal unquoted value into bool`)},
// additional tests for disallowUnknownFields
{
@@ -894,6 +897,18 @@ var unmarshalTests = []unmarshalTest{
ptr: new(mapStringToStringData),
err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"},
},
+
+ // trying to decode JSON arrays or objects via TextUnmarshaler
+ {
+ in: `[1, 2, 3]`,
+ ptr: new(MustNotUnmarshalText),
+ err: &UnmarshalTypeError{Value: "array", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
+ },
+ {
+ in: `{"foo": "bar"}`,
+ ptr: new(MustNotUnmarshalText),
+ err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
+ },
}
func TestMarshal(t *testing.T) {
@@ -1955,10 +1970,12 @@ type unexportedFields struct {
Name string
m map[string]interface{} `json:"-"`
m2 map[string]interface{} `json:"abcd"`
+
+ s []int `json:"-"`
}
func TestUnmarshalUnexported(t *testing.T) {
- input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
+ input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}, "s": [2, 3]}`
want := &unexportedFields{Name: "Bob"}
out := &unexportedFields{}