119 lines
3.5 KiB
Diff
119 lines
3.5 KiB
Diff
From 96ffe2941c07e4a6b92357b6eb8739304f839bef Mon Sep 17 00:00:00 2001
|
|
From: jingrui <jingrui@huawei.com>
|
|
Date: Wed, 23 Dec 2020 15:58:14 +0800
|
|
Subject: [PATCH 1/2] encoding/xml: handle leading, trailing, or double colons
|
|
in names
|
|
|
|
Before this change, <:name> would parse as <name>, which could cause
|
|
issues in applications that rely on the parse-encode cycle to
|
|
round-trip. Similarly, <x name:=""> would parse as expected but then
|
|
have the attribute dropped when serializing because its name was empty.
|
|
Finally, <a:b:c> would parse and get serialized incorrectly. All these
|
|
values are invalid XML, but to minimize the impact of this change, we
|
|
parse them whole into Name.Local.
|
|
|
|
This issue was reported by Juho Nurminen of Mattermost as it leads to
|
|
round-trip mismatches. See #43168. It's not being fixed in a security
|
|
release because round-trip stability is not a currently supported
|
|
security property of encoding/xml, and we don't believe these fixes
|
|
would be sufficient to reliably guarantee it in the future.
|
|
|
|
Fixes CVE-2020-29509
|
|
Fixes CVE-2020-29511
|
|
Updates #43168
|
|
Conflict: NA
|
|
Reference: https://go-review.googlesource.com/c/go/+/277892
|
|
Change-Id: I68321c4d867305046f664347192948a889af3c7f
|
|
|
|
Signed-off-by: jingrui <jingrui@huawei.com>
|
|
---
|
|
src/encoding/xml/xml.go | 5 ++--
|
|
src/encoding/xml/xml_test.go | 58 ++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 61 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go
|
|
index ca059440a1..073ceee1b2 100644
|
|
--- a/src/encoding/xml/xml.go
|
|
+++ b/src/encoding/xml/xml.go
|
|
@@ -1152,8 +1152,9 @@ func (d *Decoder) nsname() (name Name, ok bool) {
|
|
if !ok {
|
|
return
|
|
}
|
|
- i := strings.Index(s, ":")
|
|
- if i < 0 {
|
|
+ if strings.Count(s, ":") > 1 {
|
|
+ name.Local = s
|
|
+ } else if i := strings.Index(s, ":"); i < 1 || i > len(s)-2 {
|
|
name.Local = s
|
|
} else {
|
|
name.Space = s[0:i]
|
|
diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go
|
|
index ee4ffa2420..eef4dc3001 100644
|
|
--- a/src/encoding/xml/xml_test.go
|
|
+++ b/src/encoding/xml/xml_test.go
|
|
@@ -898,3 +898,61 @@ func TestTokenUnmarshaler(t *testing.T) {
|
|
d := NewTokenDecoder(tokReader{})
|
|
d.Decode(&Failure{})
|
|
}
|
|
+
|
|
+func testRoundTrip(t *testing.T, input string) {
|
|
+ t.Logf("input: %q", input)
|
|
+ d := NewDecoder(strings.NewReader(input))
|
|
+ var tokens []Token
|
|
+ var buf bytes.Buffer
|
|
+ e := NewEncoder(&buf)
|
|
+ for {
|
|
+ tok, err := d.Token()
|
|
+ if err == io.EOF {
|
|
+ break
|
|
+ }
|
|
+ if err != nil {
|
|
+ t.Fatalf("invalid input: %v", err)
|
|
+ }
|
|
+ if err := e.EncodeToken(tok); err != nil {
|
|
+ t.Fatalf("failed to re-encode input: %v", err)
|
|
+ }
|
|
+ tokens = append(tokens, CopyToken(tok))
|
|
+ }
|
|
+ if err := e.Flush(); err != nil {
|
|
+ t.Fatal(err)
|
|
+ }
|
|
+ t.Logf("output: %q", buf.String())
|
|
+
|
|
+ d = NewDecoder(&buf)
|
|
+ for {
|
|
+ tok, err := d.Token()
|
|
+ if err == io.EOF {
|
|
+ break
|
|
+ }
|
|
+ if err != nil {
|
|
+ t.Fatalf("failed to decode output: %v", err)
|
|
+ }
|
|
+ if len(tokens) == 0 {
|
|
+ t.Fatalf("unexpected token: %#v", tok)
|
|
+ }
|
|
+ a, b := tokens[0], tok
|
|
+ if !reflect.DeepEqual(a, b) {
|
|
+ t.Fatalf("token mismatch: %#v vs %#v", a, b)
|
|
+ }
|
|
+ tokens = tokens[1:]
|
|
+ }
|
|
+ if len(tokens) > 0 {
|
|
+ t.Fatalf("lost tokens: %#v", tokens)
|
|
+ }
|
|
+}
|
|
+
|
|
+func TestRoundTrip(t *testing.T) {
|
|
+ tests := map[string]string{
|
|
+ "leading colon": `<::Test ::foo="bar"><:::Hello></:::Hello><Hello></Hello></::Test>`,
|
|
+ "trailing colon": `<foo abc:="x"></foo>`,
|
|
+ "double colon": `<x:y:foo></x:y:foo>`,
|
|
+ }
|
|
+ for name, input := range tests {
|
|
+ t.Run(name, func(t *testing.T) { testRoundTrip(t, input) })
|
|
+ }
|
|
+}
|
|
--
|
|
2.17.1
|
|
|