aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding/json
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-07-10 10:51:40 -0700
committerIan Lance Taylor <iant@golang.org>2020-07-10 11:30:23 -0700
commit2b6d99468d4d988fd5f5ea3e9be41a3dc95a1291 (patch)
treecb989c3bca6130c4649a3cd44041adc4f4b1c2c2 /libgo/go/encoding/json
parent510125d2272175f47b26227fbe9b8c8c5abfd988 (diff)
downloadgcc-2b6d99468d4d988fd5f5ea3e9be41a3dc95a1291.zip
gcc-2b6d99468d4d988fd5f5ea3e9be41a3dc95a1291.tar.gz
gcc-2b6d99468d4d988fd5f5ea3e9be41a3dc95a1291.tar.bz2
libgo: update to Go 1.14.4 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/241999
Diffstat (limited to 'libgo/go/encoding/json')
-rw-r--r--libgo/go/encoding/json/decode.go5
-rw-r--r--libgo/go/encoding/json/decode_test.go33
-rw-r--r--libgo/go/encoding/json/encode.go11
-rw-r--r--libgo/go/encoding/json/encode_test.go87
-rw-r--r--libgo/go/encoding/json/stream_test.go8
5 files changed, 105 insertions, 39 deletions
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index b434846..b60e2bb 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -1217,6 +1217,11 @@ func (d *decodeState) unquoteBytes(s []byte) (t []byte, ok bool) {
if r == -1 {
return s, true
}
+ // Only perform up to one safe unquote for each re-scanned string
+ // literal. In some edge cases, the decoder unquotes a literal a second
+ // time, even after another literal has been re-scanned. Thus, only the
+ // first unquote can safely use safeUnquote.
+ d.safeUnquote = 0
b := make([]byte, len(s)+2*utf8.UTFMax)
w := copy(b, s[0:r])
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index 498bd97..a49181e 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -2419,7 +2419,7 @@ func (m *textUnmarshalerString) UnmarshalText(text []byte) error {
return nil
}
-// Test unmarshal to a map, with map key is a user defined type.
+// Test unmarshal to a map, where the map key is a user defined type.
// See golang.org/issues/34437.
func TestUnmarshalMapWithTextUnmarshalerStringKey(t *testing.T) {
var p map[textUnmarshalerString]string
@@ -2428,6 +2428,35 @@ func TestUnmarshalMapWithTextUnmarshalerStringKey(t *testing.T) {
}
if _, ok := p["foo"]; !ok {
- t.Errorf(`Key "foo" is not existed in map: %v`, p)
+ t.Errorf(`Key "foo" does not exist in map: %v`, p)
+ }
+}
+
+func TestUnmarshalRescanLiteralMangledUnquote(t *testing.T) {
+ // See golang.org/issues/38105.
+ var p map[textUnmarshalerString]string
+ if err := Unmarshal([]byte(`{"开源":"12345开源"}`), &p); err != nil {
+ t.Fatalf("Unmarshal unexpected error: %v", err)
+ }
+ if _, ok := p["开源"]; !ok {
+ t.Errorf(`Key "开源" does not exist in map: %v`, p)
+ }
+
+ // See golang.org/issues/38126.
+ type T struct {
+ F1 string `json:"F1,string"`
+ }
+ t1 := T{"aaa\tbbb"}
+
+ b, err := Marshal(t1)
+ if err != nil {
+ t.Fatalf("Marshal unexpected error: %v", err)
+ }
+ var t2 T
+ if err := Unmarshal(b, &t2); err != nil {
+ t.Fatalf("Unmarshal unexpected error: %v", err)
+ }
+ if t1 != t2 {
+ t.Errorf("Marshal and Unmarshal roundtrip mismatch: want %q got %q", t1, t2)
}
}
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index 39cdaeb..b351cf3 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -635,11 +635,12 @@ func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
return
}
if opts.quoted {
- b := make([]byte, 0, v.Len()+2)
- b = append(b, '"')
- b = append(b, []byte(v.String())...)
- b = append(b, '"')
- e.stringBytes(b, opts.escapeHTML)
+ e2 := newEncodeState()
+ // Since we encode the string twice, we only need to escape HTML
+ // the first time.
+ e2.string(v.String(), opts.escapeHTML)
+ e.stringBytes(e2.Bytes(), false)
+ encodeStatePool.Put(e2)
} else {
e.string(v.String(), opts.escapeHTML)
}
diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go
index 5110c7d..7290eca 100644
--- a/libgo/go/encoding/json/encode_test.go
+++ b/libgo/go/encoding/json/encode_test.go
@@ -79,37 +79,66 @@ type StringTag struct {
NumberStr Number `json:",string"`
}
-var stringTagExpected = `{
- "BoolStr": "true",
- "IntStr": "42",
- "UintptrStr": "44",
- "StrStr": "\"xzbit\"",
- "NumberStr": "46"
-}`
-
-func TestStringTag(t *testing.T) {
- var s StringTag
- s.BoolStr = true
- s.IntStr = 42
- s.UintptrStr = 44
- s.StrStr = "xzbit"
- s.NumberStr = "46"
- got, err := MarshalIndent(&s, "", " ")
- if err != nil {
- t.Fatal(err)
- }
- if got := string(got); got != stringTagExpected {
- t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
+func TestRoundtripStringTag(t *testing.T) {
+ tests := []struct {
+ name string
+ in StringTag
+ want string // empty to just test that we roundtrip
+ }{
+ {
+ name: "AllTypes",
+ in: StringTag{
+ BoolStr: true,
+ IntStr: 42,
+ UintptrStr: 44,
+ StrStr: "xzbit",
+ NumberStr: "46",
+ },
+ want: `{
+ "BoolStr": "true",
+ "IntStr": "42",
+ "UintptrStr": "44",
+ "StrStr": "\"xzbit\"",
+ "NumberStr": "46"
+ }`,
+ },
+ {
+ // See golang.org/issues/38173.
+ name: "StringDoubleEscapes",
+ in: StringTag{
+ StrStr: "\b\f\n\r\t\"\\",
+ NumberStr: "0", // just to satisfy the roundtrip
+ },
+ want: `{
+ "BoolStr": "false",
+ "IntStr": "0",
+ "UintptrStr": "0",
+ "StrStr": "\"\\u0008\\u000c\\n\\r\\t\\\"\\\\\"",
+ "NumberStr": "0"
+ }`,
+ },
}
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ // Indent with a tab prefix to make the multi-line string
+ // literals in the table nicer to read.
+ got, err := MarshalIndent(&test.in, "\t\t\t", "\t")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got := string(got); got != test.want {
+ t.Fatalf(" got: %s\nwant: %s\n", got, test.want)
+ }
- // Verify that it round-trips.
- var s2 StringTag
- err = NewDecoder(bytes.NewReader(got)).Decode(&s2)
- if err != nil {
- t.Fatalf("Decode: %v", err)
- }
- if !reflect.DeepEqual(s, s2) {
- t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
+ // Verify that it round-trips.
+ var s2 StringTag
+ if err := Unmarshal(got, &s2); err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+ if !reflect.DeepEqual(test.in, s2) {
+ t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", test.in, string(got), s2)
+ }
+ })
}
}
diff --git a/libgo/go/encoding/json/stream_test.go b/libgo/go/encoding/json/stream_test.go
index ebb4f23..c9e5334 100644
--- a/libgo/go/encoding/json/stream_test.go
+++ b/libgo/go/encoding/json/stream_test.go
@@ -144,14 +144,15 @@ func TestEncoderSetEscapeHTML(t *testing.T) {
},
{
"stringOption", stringOption,
- `{"bar":"\"\u003chtml\u003efoobar\u003c/html\u003e\""}`,
+ `{"bar":"\"\\u003chtml\\u003efoobar\\u003c/html\\u003e\""}`,
`{"bar":"\"<html>foobar</html>\""}`,
},
} {
var buf bytes.Buffer
enc := NewEncoder(&buf)
if err := enc.Encode(tt.v); err != nil {
- t.Fatalf("Encode(%s): %s", tt.name, err)
+ t.Errorf("Encode(%s): %s", tt.name, err)
+ continue
}
if got := strings.TrimSpace(buf.String()); got != tt.wantEscape {
t.Errorf("Encode(%s) = %#q, want %#q", tt.name, got, tt.wantEscape)
@@ -159,7 +160,8 @@ func TestEncoderSetEscapeHTML(t *testing.T) {
buf.Reset()
enc.SetEscapeHTML(false)
if err := enc.Encode(tt.v); err != nil {
- t.Fatalf("SetEscapeHTML(false) Encode(%s): %s", tt.name, err)
+ t.Errorf("SetEscapeHTML(false) Encode(%s): %s", tt.name, err)
+ continue
}
if got := strings.TrimSpace(buf.String()); got != tt.want {
t.Errorf("SetEscapeHTML(false) Encode(%s) = %#q, want %#q",