summaryrefslogtreecommitdiff
path: root/libgo/go/encoding/xml/marshal.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/encoding/xml/marshal.go')
-rw-r--r--libgo/go/encoding/xml/marshal.go59
1 files changed, 55 insertions, 4 deletions
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go
index 8c6342013d3..86d1422a5bd 100644
--- a/libgo/go/encoding/xml/marshal.go
+++ b/libgo/go/encoding/xml/marshal.go
@@ -173,6 +173,7 @@ func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
}
var (
+ begComment = []byte("<!--")
endComment = []byte("-->")
endProcInst = []byte("?>")
endDirective = []byte(">")
@@ -191,6 +192,7 @@ var (
// EncodeToken allows writing a ProcInst with Target set to "xml" only as the first token
// in the stream.
func (enc *Encoder) EncodeToken(t Token) error {
+
p := &enc.p
switch t := t.(type) {
case StartElement:
@@ -202,7 +204,7 @@ func (enc *Encoder) EncodeToken(t Token) error {
return err
}
case CharData:
- EscapeText(p, t)
+ escapeText(p, t, false)
case Comment:
if bytes.Contains(t, endComment) {
return fmt.Errorf("xml: EncodeToken of Comment containing --> marker")
@@ -231,16 +233,59 @@ func (enc *Encoder) EncodeToken(t Token) error {
}
p.WriteString("?>")
case Directive:
- if bytes.Contains(t, endDirective) {
- return fmt.Errorf("xml: EncodeToken of Directive containing > marker")
+ if !isValidDirective(t) {
+ return fmt.Errorf("xml: EncodeToken of Directive containing wrong < or > markers")
}
p.WriteString("<!")
p.Write(t)
p.WriteString(">")
+ default:
+ return fmt.Errorf("xml: EncodeToken of invalid token type")
+
}
return p.cachedWriteError()
}
+// isValidDirective reports whether dir is a valid directive text,
+// meaning angle brackets are matched, ignoring comments and strings.
+func isValidDirective(dir Directive) bool {
+ var (
+ depth int
+ inquote uint8
+ incomment bool
+ )
+ for i, c := range dir {
+ switch {
+ case incomment:
+ if c == '>' {
+ if n := 1 + i - len(endComment); n >= 0 && bytes.Equal(dir[n:i+1], endComment) {
+ incomment = false
+ }
+ }
+ // Just ignore anything in comment
+ case inquote != 0:
+ if c == inquote {
+ inquote = 0
+ }
+ // Just ignore anything within quotes
+ case c == '\'' || c == '"':
+ inquote = c
+ case c == '<':
+ if i+len(begComment) < len(dir) && bytes.Equal(dir[i:i+len(begComment)], begComment) {
+ incomment = true
+ } else {
+ depth++
+ }
+ case c == '>':
+ if depth == 0 {
+ return false
+ }
+ depth--
+ }
+ }
+ return depth == 0 && inquote == 0 && !incomment
+}
+
// Flush flushes any buffered XML to the underlying writer.
// See the EncodeToken documentation for details about when it is necessary.
func (enc *Encoder) Flush() error {
@@ -724,6 +769,9 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
switch finfo.flags & fMode {
case fCharData:
+ if err := s.trim(finfo.parents); err != nil {
+ return err
+ }
if vf.CanInterface() && vf.Type().Implements(textMarshalerType) {
data, err := vf.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
@@ -767,6 +815,9 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
continue
case fComment:
+ if err := s.trim(finfo.parents); err != nil {
+ return err
+ }
k := vf.Kind()
if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
@@ -894,7 +945,7 @@ func (s *parentStack) trim(parents []string) error {
return err
}
}
- s.stack = parents[:split]
+ s.stack = s.stack[:split]
return nil
}