]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: escape output from Marshalers.
authorDavid Symonds <dsymonds@golang.org>
Thu, 1 Mar 2012 06:41:59 +0000 (17:41 +1100)
committerDavid Symonds <dsymonds@golang.org>
Thu, 1 Mar 2012 06:41:59 +0000 (17:41 +1100)
Fixes #3127.

R=rsc, r
CC=golang-dev
https://golang.org/cl/5707054

src/pkg/encoding/json/encode.go
src/pkg/encoding/json/encode_test.go
src/pkg/encoding/json/indent.go

index f98071777f0e968b646710af0f91454d05289437..5425a3a90a125e6ed3f31d679e87192f28ac88eb 100644 (file)
@@ -260,7 +260,7 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
                b, err := m.MarshalJSON()
                if err == nil {
                        // copy JSON into buffer, checking validity.
-                       err = Compact(&e.Buffer, b)
+                       err = compact(&e.Buffer, b, true)
                }
                if err != nil {
                        e.error(&MarshalerError{v.Type(), err})
index 7a726a91c47bb47816e42e761de3944ebb4ca8ea..cb1c77eb529f7ab112606f61eb638bd947f4c29e 100644 (file)
@@ -167,3 +167,22 @@ func TestRefValMarshal(t *testing.T) {
                t.Errorf("got %q, want %q", got, want)
        }
 }
+
+// C implements Marshaler and returns unescaped JSON.
+type C int
+
+func (C) MarshalJSON() ([]byte, error) {
+       return []byte(`"<&>"`), nil
+}
+
+func TestMarshalerEscaping(t *testing.T) {
+       var c C
+       const want = `"\u003c\u0026\u003e"`
+       b, err := Marshal(c)
+       if err != nil {
+               t.Fatalf("Marshal: %v", err)
+       }
+       if got := string(b); got != want {
+               t.Errorf("got %q, want %q", got, want)
+       }
+}
index 5ba19b07ac652d73564cf56463545b93f4d20e0f..e8dfa4ec43630bb745c0e01346caa6999d51db02 100644 (file)
@@ -9,11 +9,24 @@ import "bytes"
 // Compact appends to dst the JSON-encoded src with
 // insignificant space characters elided.
 func Compact(dst *bytes.Buffer, src []byte) error {
+       return compact(dst, src, false)
+}
+
+func compact(dst *bytes.Buffer, src []byte, escape bool) error {
        origLen := dst.Len()
        var scan scanner
        scan.reset()
        start := 0
        for i, c := range src {
+               if escape && (c == '<' || c == '>' || c == '&') {
+                       if start < i {
+                               dst.Write(src[start:i])
+                       }
+                       dst.WriteString(`\u00`)
+                       dst.WriteByte(hex[c>>4])
+                       dst.WriteByte(hex[c&0xF])
+                       start = i + 1
+               }
                v := scan.step(&scan, int(c))
                if v >= scanSkipSpace {
                        if v == scanError {