aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json
diff options
context:
space:
mode:
authorAlexander Yastrebov <yastrebov.alex@gmail.com>2023-10-05 21:55:06 +0000
committerMichael Pratt <mpratt@google.com>2023-10-06 20:19:31 +0000
commit67fb851bd5daec80a68287358b078035e48ce84e (patch)
tree3142526bea65d2e49c4cf707ac02c8f11a8f2f48 /src/encoding/json
parentb01cb72eb7728faa95fbb82bae1183df137f5867 (diff)
downloadgo-67fb851bd5daec80a68287358b078035e48ce84e.tar.xz
encoding/json: fix appendCompact escaping
CL 469555 changed Compact to use append instead of bytes.Buffer. appendCompact iterates over input src slice and performs escaping of certain characters. To optimize copying it does not copy characters one by one but keeps track of the start offset of the data to copy when it reaches next character to escape or the end of the input. This start offset may become greater than input character offset so copying of preceding data should check this condition. CL 469555 removed boundary checks for copying data preceding escaped characters and this change restores them. Fixes https://github.com/golang/go/issues/63379 Change-Id: I5b7856239f256c67faf58834705675c0aea08cc2 GitHub-Last-Rev: 661576fb54951a05a8399beb3f9ac2a2f9a340b4 GitHub-Pull-Request: golang/go#63400 Reviewed-on: https://go-review.googlesource.com/c/go/+/533275 Run-TryBot: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Benny Siegert <bsiegert@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/encoding/json')
-rw-r--r--src/encoding/json/encode_test.go26
-rw-r--r--src/encoding/json/indent.go18
2 files changed, 39 insertions, 5 deletions
diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go
index 9c37028037..53259f4a9b 100644
--- a/src/encoding/json/encode_test.go
+++ b/src/encoding/json/encode_test.go
@@ -1193,3 +1193,29 @@ func TestMarshalerError(t *testing.T) {
})
}
}
+
+type marshaledValue string
+
+func (v marshaledValue) MarshalJSON() ([]byte, error) {
+ return []byte(v), nil
+}
+
+func TestIssue63379(t *testing.T) {
+ for _, v := range []string{
+ "[]<",
+ "[]>",
+ "[]&",
+ "[]\u2028",
+ "[]\u2029",
+ "{}<",
+ "{}>",
+ "{}&",
+ "{}\u2028",
+ "{}\u2029",
+ } {
+ _, err := Marshal(marshaledValue(v))
+ if err == nil {
+ t.Errorf("expected error for %q", v)
+ }
+ }
+}
diff --git a/src/encoding/json/indent.go b/src/encoding/json/indent.go
index 26bb5d2e47..01bfdf65e7 100644
--- a/src/encoding/json/indent.go
+++ b/src/encoding/json/indent.go
@@ -53,29 +53,37 @@ func appendCompact(dst, src []byte, escape bool) ([]byte, error) {
start := 0
for i, c := range src {
if escape && (c == '<' || c == '>' || c == '&') {
- dst = append(dst, src[start:i]...)
+ if start < i {
+ dst = append(dst, src[start:i]...)
+ }
dst = append(dst, '\\', 'u', '0', '0', hex[c>>4], hex[c&0xF])
start = i + 1
}
// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
if escape && c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
- dst = append(dst, src[start:i]...)
+ if start < i {
+ dst = append(dst, src[start:i]...)
+ }
dst = append(dst, '\\', 'u', '2', '0', '2', hex[src[i+2]&0xF])
- start = i + len("\u2029")
+ start = i + 3
}
v := scan.step(scan, c)
if v >= scanSkipSpace {
if v == scanError {
break
}
- dst = append(dst, src[start:i]...)
+ if start < i {
+ dst = append(dst, src[start:i]...)
+ }
start = i + 1
}
}
if scan.eof() == scanError {
return dst[:origLen], scan.err
}
- dst = append(dst, src[start:]...)
+ if start < len(src) {
+ dst = append(dst, src[start:]...)
+ }
return dst, nil
}