diff options
author | Jason Del Ponte <delpontej@gmail.com> | 2014-05-12 23:35:56 -0400 |
---|---|---|
committer | Jason Del Ponte <delpontej@gmail.com> | 2014-05-12 23:35:56 -0400 |
commit | 6951fab0f4b4c211c7a60c872bdd746df637e915 (patch) | |
tree | 9f196453085972f015f2f855011ce85db96d9b1d /src/pkg | |
parent | 1ae54c8873f91d5253a964f6eb7a9eb0fb5da609 (diff) | |
download | go-6951fab0f4b4c211c7a60c872bdd746df637e915.tar.gz |
encoding/xml: fix to allow xml declaration with EncodeToken
This changes allows the first token encoded to be a xml declaration. A ProcInst with target of xml. Any other ProcInst after that with a target of xml will fail
Fixes Issue 7380.
LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://codereview.appspot.com/72410043
Committer: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/pkg')
-rw-r--r-- | src/pkg/encoding/xml/marshal.go | 11 | ||||
-rw-r--r-- | src/pkg/encoding/xml/marshal_test.go | 36 |
2 files changed, 44 insertions, 3 deletions
diff --git a/src/pkg/encoding/xml/marshal.go b/src/pkg/encoding/xml/marshal.go index d9522e0b3..8c6342013 100644 --- a/src/pkg/encoding/xml/marshal.go +++ b/src/pkg/encoding/xml/marshal.go @@ -184,10 +184,12 @@ var ( // EncodeToken does not call Flush, because usually it is part of a larger operation // such as Encode or EncodeElement (or a custom Marshaler's MarshalXML invoked // during those), and those will call Flush when finished. -// // Callers that create an Encoder and then invoke EncodeToken directly, without // using Encode or EncodeElement, need to call Flush when finished to ensure // that the XML is written to the underlying writer. +// +// 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) { @@ -210,7 +212,12 @@ func (enc *Encoder) EncodeToken(t Token) error { p.WriteString("-->") return p.cachedWriteError() case ProcInst: - if t.Target == "xml" || !isNameString(t.Target) { + // First token to be encoded which is also a ProcInst with target of xml + // is the xml declaration. The only ProcInst where target of xml is allowed. + if t.Target == "xml" && p.Buffered() != 0 { + return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded") + } + if !isNameString(t.Target) { return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target") } if bytes.Contains(t.Inst, endProcInst) { diff --git a/src/pkg/encoding/xml/marshal_test.go b/src/pkg/encoding/xml/marshal_test.go index ecb9998da..638158397 100644 --- a/src/pkg/encoding/xml/marshal_test.go +++ b/src/pkg/encoding/xml/marshal_test.go @@ -1203,7 +1203,7 @@ var encodeTokenTests = []struct { {Comment("foo"), "<!--foo-->", true}, {Comment("foo-->"), "", false}, {ProcInst{"Target", []byte("Instruction")}, "<?Target Instruction?>", true}, - {ProcInst{"xml", []byte("Instruction")}, "", false}, + {ProcInst{"", []byte("Instruction")}, "", false}, {ProcInst{"Target", []byte("Instruction?>")}, "", false}, {Directive("foo"), "<!foo>", true}, {Directive("foo>"), "", false}, @@ -1230,3 +1230,37 @@ func TestEncodeToken(t *testing.T) { } } } + +func TestProcInstEncodeToken(t *testing.T) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + + if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err != nil { + t.Fatalf("enc.EncodeToken: expected to be able to encode xml target ProcInst as first token, %s", err) + } + + if err := enc.EncodeToken(ProcInst{"Target", []byte("Instruction")}); err != nil { + t.Fatalf("enc.EncodeToken: expected to be able to add non-xml target ProcInst") + } + + if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err == nil { + t.Fatalf("enc.EncodeToken: expected to not be allowed to encode xml target ProcInst when not first token") + } +} + +func TestDecodeEncode(t *testing.T) { + var in, out bytes.Buffer + in.WriteString(`<?xml version="1.0" encoding="UTF-8"?> +<?Target Instruction?> +<root> +</root> +`) + dec := NewDecoder(&in) + enc := NewEncoder(&out) + for tok, err := dec.Token(); err == nil; tok, err = dec.Token() { + err = enc.EncodeToken(tok) + if err != nil { + t.Fatalf("enc.EncodeToken: Unable to encode token (%#v), %d", tok, err) + } + } +} |