1
0
mirror of https://github.com/golang/go synced 2024-11-21 19:34:46 -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:
Russ Cox 2010-12-13 15:51:11 -05:00
parent 3a2ba994b6
commit 287e45e241
2 changed files with 52 additions and 11 deletions

View File

@ -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 {

View File

@ -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('\\') if start < i {
fallthrough e.WriteString(s[start:i])
default: }
e.WriteRune(c) 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('"')
} }