mirror of
https://github.com/golang/go.git
synced 2025-11-10 13:41:05 +00:00
encoding/json: obey SetEscapeHTML in all MarshalJSON cases
It wasn't obeyed in the case where the MarshalJSON method uses a pointer
receiver, and the encoder grabs the address of a value to find that
method. addrMarshalerEncoder is the function that does this work, but it
ignored opts.escapeHTML.
Here's the before and after of the added test case, which was failing
before the fix. Now the two cases are correct and consistent.
{"NonPtr":"<str>","Ptr":"\u003cstr\u003e"}
{"NonPtr":"<str>","Ptr":"<str>"}
Fixes #32896.
Change-Id: Idc53077ece074973558bd3bb5ad036380db0d02c
Reviewed-on: https://go-review.googlesource.com/c/go/+/184757
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: Caleb Spare <cespare@gmail.com>
This commit is contained in:
parent
a2fb5cd823
commit
13327f219e
2 changed files with 28 additions and 2 deletions
|
|
@ -460,7 +460,7 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addrMarshalerEncoder(e *encodeState, v reflect.Value, _ encOpts) {
|
func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
|
||||||
va := v.Addr()
|
va := v.Addr()
|
||||||
if va.IsNil() {
|
if va.IsNil() {
|
||||||
e.WriteString("null")
|
e.WriteString("null")
|
||||||
|
|
@ -470,7 +470,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, _ encOpts) {
|
||||||
b, err := m.MarshalJSON()
|
b, err := m.MarshalJSON()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// copy JSON into buffer, checking validity.
|
// copy JSON into buffer, checking validity.
|
||||||
err = compact(&e.Buffer, b, true)
|
err = compact(&e.Buffer, b, opts.escapeHTML)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.error(&MarshalerError{v.Type(), err})
|
e.error(&MarshalerError{v.Type(), err})
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,18 @@ func TestEncoderIndent(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type strMarshaler string
|
||||||
|
|
||||||
|
func (s strMarshaler) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type strPtrMarshaler string
|
||||||
|
|
||||||
|
func (s *strPtrMarshaler) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(*s), nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestEncoderSetEscapeHTML(t *testing.T) {
|
func TestEncoderSetEscapeHTML(t *testing.T) {
|
||||||
var c C
|
var c C
|
||||||
var ct CText
|
var ct CText
|
||||||
|
|
@ -97,6 +109,15 @@ func TestEncoderSetEscapeHTML(t *testing.T) {
|
||||||
Valid int `json:"<>&#! "`
|
Valid int `json:"<>&#! "`
|
||||||
Invalid int `json:"\\"`
|
Invalid int `json:"\\"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This case is particularly interesting, as we force the encoder to
|
||||||
|
// take the address of the Ptr field to use its MarshalJSON method. This
|
||||||
|
// is why the '&' is important.
|
||||||
|
marshalerStruct := &struct {
|
||||||
|
NonPtr strMarshaler
|
||||||
|
Ptr strPtrMarshaler
|
||||||
|
}{`"<str>"`, `"<str>"`}
|
||||||
|
|
||||||
for _, tt := range []struct {
|
for _, tt := range []struct {
|
||||||
name string
|
name string
|
||||||
v interface{}
|
v interface{}
|
||||||
|
|
@ -111,6 +132,11 @@ func TestEncoderSetEscapeHTML(t *testing.T) {
|
||||||
`{"\u003c\u003e\u0026#! ":0,"Invalid":0}`,
|
`{"\u003c\u003e\u0026#! ":0,"Invalid":0}`,
|
||||||
`{"<>&#! ":0,"Invalid":0}`,
|
`{"<>&#! ":0,"Invalid":0}`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`"<str>"`, marshalerStruct,
|
||||||
|
`{"NonPtr":"\u003cstr\u003e","Ptr":"\u003cstr\u003e"}`,
|
||||||
|
`{"NonPtr":"<str>","Ptr":"<str>"}`,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := NewEncoder(&buf)
|
enc := NewEncoder(&buf)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue