mirror of
https://github.com/golang/go
synced 2024-11-22 01:34:41 -07:00
json: check for invalid UTF-8
Fixes #1250. R=r CC=golang-dev https://golang.org/cl/3562042
This commit is contained in:
parent
3a2ba994b6
commit
287e45e241
@ -102,6 +102,20 @@ func TestMarshal(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshalBadUTF8(t *testing.T) {
|
||||||
|
s := "hello\xffworld"
|
||||||
|
b, err := Marshal(s)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("Marshal bad UTF8: no error")
|
||||||
|
}
|
||||||
|
if len(b) != 0 {
|
||||||
|
t.Fatal("Marshal returned data")
|
||||||
|
}
|
||||||
|
if _, ok := err.(*InvalidUTF8Error); !ok {
|
||||||
|
t.Fatal("Marshal did not return InvalidUTF8Error: %T %v", err, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnmarshal(t *testing.T) {
|
func TestUnmarshal(t *testing.T) {
|
||||||
var scan scanner
|
var scan scanner
|
||||||
for i, tt := range unmarshalTests {
|
for i, tt := range unmarshalTests {
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Marshal returns the JSON encoding of v.
|
// Marshal returns the JSON encoding of v.
|
||||||
@ -129,6 +130,14 @@ func (e *UnsupportedTypeError) String() string {
|
|||||||
return "json: unsupported type: " + e.Type.String()
|
return "json: unsupported type: " + e.Type.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InvalidUTF8Error struct {
|
||||||
|
S string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *InvalidUTF8Error) String() string {
|
||||||
|
return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
|
||||||
|
}
|
||||||
|
|
||||||
type MarshalerError struct {
|
type MarshalerError struct {
|
||||||
Type reflect.Type
|
Type reflect.Type
|
||||||
Error os.Error
|
Error os.Error
|
||||||
@ -281,18 +290,36 @@ func (sv stringValues) get(i int) string { return sv[i].(*reflect.StringValue)
|
|||||||
|
|
||||||
func (e *encodeState) string(s string) {
|
func (e *encodeState) string(s string) {
|
||||||
e.WriteByte('"')
|
e.WriteByte('"')
|
||||||
for _, c := range s {
|
start := 0
|
||||||
switch {
|
for i := 0; i < len(s); {
|
||||||
case c < 0x20:
|
if b := s[i]; b < utf8.RuneSelf {
|
||||||
e.WriteString(`\u00`)
|
if 0x20 <= b && b != '\\' && b != '"' {
|
||||||
e.WriteByte(hex[c>>4])
|
i++
|
||||||
e.WriteByte(hex[c&0xF])
|
continue
|
||||||
case c == '\\' || c == '"':
|
|
||||||
e.WriteByte('\\')
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
e.WriteRune(c)
|
|
||||||
}
|
}
|
||||||
|
if start < i {
|
||||||
|
e.WriteString(s[start:i])
|
||||||
|
}
|
||||||
|
if b == '\\' || b == '"' {
|
||||||
|
e.WriteByte('\\')
|
||||||
|
e.WriteByte(b)
|
||||||
|
} else {
|
||||||
|
e.WriteString(`\u00`)
|
||||||
|
e.WriteByte(hex[b>>4])
|
||||||
|
e.WriteByte(hex[b&0xF])
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
start = i
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, size := utf8.DecodeRuneInString(s[i:])
|
||||||
|
if c == utf8.RuneError && size == 1 {
|
||||||
|
e.error(&InvalidUTF8Error{s})
|
||||||
|
}
|
||||||
|
i += size
|
||||||
|
}
|
||||||
|
if start < len(s) {
|
||||||
|
e.WriteString(s[start:])
|
||||||
}
|
}
|
||||||
e.WriteByte('"')
|
e.WriteByte('"')
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user