mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
encoding/xml: improve marshaller sanity checks of directives
When building a directive, the current sanity check prevents a '>' to be used, which makes a DOCTYPE directive with an internal subset be rejected. It is accepted by the parser though, so what can be parsed cannot be encoded. Improved the corresponding sanity check to mirror the behavior of the parser (in the way it handles angle brackets, quotes, and comments). Fixes #10158 Change-Id: Ieffea9f870f2694548e12897f8f47babc0ea4414 Reviewed-on: https://go-review.googlesource.com/11630 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
aed74b9ddf
commit
8b6527b70e
2 changed files with 82 additions and 3 deletions
|
|
@ -173,6 +173,7 @@ func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
|
|||
}
|
||||
|
||||
var (
|
||||
begComment = []byte("<!--")
|
||||
endComment = []byte("-->")
|
||||
endProcInst = []byte("?>")
|
||||
endDirective = []byte(">")
|
||||
|
|
@ -238,8 +239,8 @@ 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)
|
||||
|
|
@ -248,6 +249,46 @@ func (enc *Encoder) EncodeToken(t Token) error {
|
|||
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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue