From 77673cf47138b1adb7cc81e0035eed81ef54f0d6 Mon Sep 17 00:00:00 2001 From: chenjiankun Date: Sat, 17 Apr 2021 17:08:48 +0800 Subject: [PATCH] fix CVE-2021-27918 --- 0025-fix-CVE-2021-27918.patch | 215 ++++++++++++++++++++++++++++++++++ golang.spec | 6 +- 2 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 0025-fix-CVE-2021-27918.patch diff --git a/0025-fix-CVE-2021-27918.patch b/0025-fix-CVE-2021-27918.patch new file mode 100644 index 0000000..ca4e361 --- /dev/null +++ b/0025-fix-CVE-2021-27918.patch @@ -0,0 +1,215 @@ +From 01444c00b012d8500c574aba65ad0525422fde8c Mon Sep 17 00:00:00 2001 +From: chenjiankun +Date: Fri, 9 Apr 2021 15:24:20 +0800 +Subject: [PATCH] fix CVE-2021-27918 + +encoding/xml in Go before 1.15.9 and 1.16.x before 1.16.1 +has an infinite loop if a custom TokenReader (for xml.NewTokenDecoder) +returns EOF in the middle of an element. This can occur in the Decode, +DecodeElement, or Skip method. + +Conflict:NA +Reference:https://github.com/golang/go/commit/91062c2e4cbbf78a108919f6ed3ded1173937cf3 +--- + src/encoding/xml/xml.go | 13 ++-- + src/encoding/xml/xml_test.go | 122 ++++++++++++++++++++++++++++++++--- + 2 files changed, 122 insertions(+), 13 deletions(-) + +diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go +index 3746018..42c103e 100644 +--- a/src/encoding/xml/xml.go ++++ b/src/encoding/xml/xml.go +@@ -285,11 +285,16 @@ func (d *Decoder) Token() (Token, error) { + if d.nextToken != nil { + 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 { +- err = d.syntaxError("unexpected EOF") ++ } else { ++ if t, err = d.rawToken(); t == nil && err != nil { ++ if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF { ++ err = d.syntaxError("unexpected EOF") ++ } ++ return nil, err + } +- return t, err ++ // We still have a token to process, so clear any ++ // errors (e.g. EOF) and proceed. ++ err = nil + } + + if !d.Strict { +diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go +index eef4dc3..19152db 100644 +--- a/src/encoding/xml/xml_test.go ++++ b/src/encoding/xml/xml_test.go +@@ -14,6 +14,111 @@ 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"}} ++ tests := []struct { ++ name string ++ tokens []Token ++ ok bool ++ }{ ++ { ++ name: "OK", ++ tokens: []Token{ ++ start, ++ start.End(), ++ }, ++ ok: true, ++ }, ++ { ++ name: "Malformed", ++ tokens: []Token{ ++ start, ++ StartElement{Name: Name{Local: "bad"}}, ++ start.End(), ++ }, ++ ok: false, ++ }, ++ } ++ for _, tc := range tests { ++ for _, eof := range []bool{true, false} { ++ name := fmt.Sprintf("%s/earlyEOF=%v", tc.name, eof) ++ t.Run(name, func(t *testing.T) { ++ d := NewTokenDecoder(&toks{ ++ earlyEOF: eof, ++ t: tc.tokens, ++ }) ++ err := d.Decode(&struct { ++ XMLName Name `xml:"test"` ++ }{}) ++ if tc.ok && err != nil { ++ t.Fatalf("d.Decode: expected nil error, got %v", err) ++ } ++ if _, ok := err.(*SyntaxError); !tc.ok && !ok { ++ t.Errorf("d.Decode: expected syntax error, got %v", err) ++ } ++ }) ++ } ++ } ++} ++ ++type toksNil struct { ++ returnEOF bool ++ t []Token ++} ++ ++func (t *toksNil) Token() (Token, error) { ++ if len(t.t) == 0 { ++ if !t.returnEOF { ++ // Return nil, nil before returning an EOF. It's legal, but ++ // discouraged. ++ t.returnEOF = true ++ return nil, nil ++ } ++ return nil, io.EOF ++ } ++ var tok Token ++ tok, t.t = t.t[0], t.t[1:] ++ return tok, nil ++} ++ ++func TestDecodeNilToken(t *testing.T) { ++ for _, strict := range []bool{true, false} { ++ name := fmt.Sprintf("Strict=%v", strict) ++ t.Run(name, func(t *testing.T) { ++ start := StartElement{Name: Name{Local: "test"}} ++ bad := StartElement{Name: Name{Local: "bad"}} ++ d := NewTokenDecoder(&toksNil{ ++ // Malformed ++ t: []Token{start, bad, start.End()}, ++ }) ++ d.Strict = strict ++ err := d.Decode(&struct { ++ XMLName Name `xml:"test"` ++ }{}) ++ if _, ok := err.(*SyntaxError); !ok { ++ t.Errorf("d.Decode: expected syntax error, got %v", err) ++ } ++ }) ++ } ++} ++ + const testInput = ` + + ]`), ++ Directive(`DOCTYPE [ ]`), + CharData("\n"), +- Directive(`DOCTYPE []`), ++ Directive(`DOCTYPE [ ]`), + CharData("\n"), +- Directive(`DOCTYPE []`), ++ Directive(`DOCTYPE [ ]`), + CharData("\n"), + } + +@@ -835,7 +940,7 @@ func (m mapper) Token() (Token, error) { + } + + func TestNewTokenDecoderIdempotent(t *testing.T) { +- d := NewDecoder(strings.NewReader(`
`)) ++ d := NewDecoder(strings.NewReader(`
`)) + d2 := NewTokenDecoder(d) + if d != d2 { + t.Error("NewTokenDecoder did not detect underlying Decoder") +@@ -900,7 +1005,6 @@ func TestTokenUnmarshaler(t *testing.T) { + } + + func testRoundTrip(t *testing.T, input string) { +- t.Logf("input: %q", input) + d := NewDecoder(strings.NewReader(input)) + var tokens []Token + var buf bytes.Buffer +@@ -921,7 +1025,6 @@ func testRoundTrip(t *testing.T, input string) { + if err := e.Flush(); err != nil { + t.Fatal(err) + } +- t.Logf("output: %q", buf.String()) + + d = NewDecoder(&buf) + for { +@@ -948,9 +1051,10 @@ func testRoundTrip(t *testing.T, input string) { + + func TestRoundTrip(t *testing.T) { + tests := map[string]string{ +- "leading colon": `<::Test ::foo="bar"><:::Hello>`, +- "trailing colon": ``, +- "double colon": ``, ++ "leading colon": `<::Test ::foo="bar"><:::Hello>`, ++ "trailing colon": ``, ++ "double colon": ``, ++ "comments in directives": `--x --> > --x ]>`, + } + for name, input := range tests { + t.Run(name, func(t *testing.T) { testRoundTrip(t, input) }) +-- +2.27.0 + diff --git a/golang.spec b/golang.spec index 2951c03..b285328 100644 --- a/golang.spec +++ b/golang.spec @@ -62,7 +62,7 @@ Name: golang Version: 1.13.15 -Release: 4 +Release: 5 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -163,6 +163,7 @@ Patch6021: 0021-golang-fix-CVE-2020-28367.patch Patch6022: 0022-fix-CVE-2020-29509-CVE-2020-29511.patch Patch6023: 0023-fix-CVE-2020-29510.patch Patch6024: 0024-crypto-elliptic-fix-P-224-field-reduction.patch +Patch6025: 0025-fix-CVE-2021-27918.patch ExclusiveArch: %{golang_arches} @@ -396,6 +397,9 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Thu Apr 17 2021 chenjiankun - 1.13.15-5 +- fix CVE-2021-27918 + * Thu Feb 18 2021 jingrui - 1.13.15-3 - fix CVE-2021-3114 -- Gitee