Commit f74eb6db authored by Olivier Saingre's avatar Olivier Saingre Committed by Russ Cox

encoding/xml: rewrite invalid code points to U+FFFD in Marshal, Escape

Fixes #4235.

R=rsc, dave, r, dr.volker.dobler
CC=golang-dev
https://golang.org/cl/7438051
parent e778f930
...@@ -1729,6 +1729,7 @@ var ( ...@@ -1729,6 +1729,7 @@ var (
esc_tab = []byte("	") esc_tab = []byte("	")
esc_nl = []byte("
") esc_nl = []byte("
")
esc_cr = []byte("
") esc_cr = []byte("
")
esc_fffd = []byte("\uFFFD") // Unicode replacement character
) )
// EscapeText writes to w the properly escaped XML equivalent // EscapeText writes to w the properly escaped XML equivalent
...@@ -1736,8 +1737,10 @@ var ( ...@@ -1736,8 +1737,10 @@ var (
func EscapeText(w io.Writer, s []byte) error { func EscapeText(w io.Writer, s []byte) error {
var esc []byte var esc []byte
last := 0 last := 0
for i, c := range s { for i := 0; i < len(s); {
switch c { r, width := utf8.DecodeRune(s[i:])
i += width
switch r {
case '"': case '"':
esc = esc_quot esc = esc_quot
case '\'': case '\'':
...@@ -1755,15 +1758,19 @@ func EscapeText(w io.Writer, s []byte) error { ...@@ -1755,15 +1758,19 @@ func EscapeText(w io.Writer, s []byte) error {
case '\r': case '\r':
esc = esc_cr esc = esc_cr
default: default:
if !isInCharacterRange(r) {
esc = esc_fffd
break
}
continue continue
} }
if _, err := w.Write(s[last:i]); err != nil { if _, err := w.Write(s[last : i-width]); err != nil {
return err return err
} }
if _, err := w.Write(esc); err != nil { if _, err := w.Write(esc); err != nil {
return err return err
} }
last = i + 1 last = i
} }
if _, err := w.Write(s[last:]); err != nil { if _, err := w.Write(s[last:]); err != nil {
return err return err
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package xml package xml
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"reflect" "reflect"
...@@ -695,6 +696,21 @@ func TestEscapeTextIOErrors(t *testing.T) { ...@@ -695,6 +696,21 @@ func TestEscapeTextIOErrors(t *testing.T) {
err := EscapeText(errWriter{}, []byte{'A'}) err := EscapeText(errWriter{}, []byte{'A'})
if err == nil || err.Error() != expectErr { if err == nil || err.Error() != expectErr {
t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr) t.Errorf("have %v, want %v", err, expectErr)
}
}
func TestEscapeTextInvalidChar(t *testing.T) {
input := []byte("A \x00 terminated string.")
expected := "A \uFFFD terminated string."
buff := new(bytes.Buffer)
if err := EscapeText(buff, input); err != nil {
t.Fatalf("have %v, want nil", err)
}
text := buff.String()
if text != expected {
t.Errorf("have %v, want %v", text, expected)
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment