]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/xml: fix token decoder on early EOF
authorSam Whited <sam@samwhited.com>
Tue, 21 Aug 2018 22:11:30 +0000 (17:11 -0500)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 30 Oct 2019 19:47:52 +0000 (19:47 +0000)
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>
src/encoding/xml/xml.go
src/encoding/xml/xml_test.go

index ca059440a1b8ed7be9585c1c8947a0d82d31f7f5..5e73dcf731660c3da429ec5164d3b97c7e35b59f 100644 (file)
@@ -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
index ee4ffa242089753a4e382634181915a82b74f6e7..efddca43e9102eb22b92232b3d4a8e06e9b0473d 100644 (file)
@@ -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"