diff options
author | Sam Whited <sam@samwhited.com> | 2018-08-21 17:11:30 -0500 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2019-10-30 19:47:52 +0000 |
commit | a05934639bde593326f8d7ed9eb3f73f9ba6eb53 (patch) | |
tree | 2cb22c7c63f0ac71bbad76f6bca32f9cf5cbb5e3 /src/encoding/xml | |
parent | cf6e6abc68fb1d20475bafaa65d9f96b23ae3773 (diff) | |
download | go-git-a05934639bde593326f8d7ed9eb3f73f9ba6eb53.tar.gz |
encoding/xml: fix token decoder on early EOF
The documentation for TokenReader suggests that implementations of the
interface may return a token and io.EOF together, indicating that it is
the last token in the stream. This is similar to io.Reader. However, if
you wrap such a TokenReader in a Decoder it complained about the EOF.
A test was added to ensure this behavior on Decoder's.
Change-Id: I9083c91d9626180d3bcf5c069a017050f3c7c4a8
Reviewed-on: https://go-review.googlesource.com/c/go/+/130556
Run-TryBot: Sam Whited <sam@samwhited.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/encoding/xml')
-rw-r--r-- | src/encoding/xml/xml.go | 5 | ||||
-rw-r--r-- | src/encoding/xml/xml_test.go | 45 |
2 files changed, 49 insertions, 1 deletions
diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go index ca059440a1..5e73dcf731 100644 --- a/src/encoding/xml/xml.go +++ b/src/encoding/xml/xml.go @@ -286,7 +286,10 @@ func (d *Decoder) Token() (Token, error) { t = d.nextToken d.nextToken = nil } else if t, err = d.rawToken(); err != nil { - if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF { + switch { + case err == io.EOF && d.t != nil: + err = nil + case err == io.EOF && d.stk != nil && d.stk.kind != stkEOF: err = d.syntaxError("unexpected EOF") } return t, err diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go index ee4ffa2420..efddca43e9 100644 --- a/src/encoding/xml/xml_test.go +++ b/src/encoding/xml/xml_test.go @@ -14,6 +14,51 @@ import ( "unicode/utf8" ) +type toks struct { + earlyEOF bool + t []Token +} + +func (t *toks) Token() (Token, error) { + if len(t.t) == 0 { + return nil, io.EOF + } + var tok Token + tok, t.t = t.t[0], t.t[1:] + if t.earlyEOF && len(t.t) == 0 { + return tok, io.EOF + } + return tok, nil +} + +func TestDecodeEOF(t *testing.T) { + start := StartElement{Name: Name{Local: "test"}} + t.Run("EarlyEOF", func(t *testing.T) { + d := NewTokenDecoder(&toks{earlyEOF: true, t: []Token{ + start, + start.End(), + }}) + err := d.Decode(&struct { + XMLName Name `xml:"test"` + }{}) + if err != nil { + t.Error(err) + } + }) + t.Run("LateEOF", func(t *testing.T) { + d := NewTokenDecoder(&toks{t: []Token{ + start, + start.End(), + }}) + err := d.Decode(&struct { + XMLName Name `xml:"test"` + }{}) + if err != nil { + t.Error(err) + } + }) +} + const testInput = ` <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |