!19 golang: sync cve fix
From: @jing-rui Reviewed-by: @caihaomin Signed-off-by: @caihaomin
This commit is contained in:
commit
8b174a38e5
363
0019-net-http-cgi-net-http-fcgi-add-Content-Type-detectio.patch
Normal file
363
0019-net-http-cgi-net-http-fcgi-add-Content-Type-detectio.patch
Normal file
@ -0,0 +1,363 @@
|
||||
From 2ad2c042555908cfd791b7e6a3318c1d3df10aeb Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Clapis <roberto@golang.org>
|
||||
Date: Wed, 26 Aug 2020 08:53:03 +0200
|
||||
Subject: [PATCH] net/http/cgi,net/http/fcgi: add Content-Type detection
|
||||
|
||||
This CL ensures that responses served via CGI and FastCGI
|
||||
have a Content-Type header based on the content of the
|
||||
response if not explicitly set by handlers.
|
||||
|
||||
If the implementers of the handler did not explicitly
|
||||
specify a Content-Type both CGI implementations would default
|
||||
to "text/html", potentially causing cross-site scripting.
|
||||
|
||||
Thanks to RedTeam Pentesting GmbH for reporting this.
|
||||
|
||||
Fixes #40928
|
||||
Fixes CVE-2020-24553
|
||||
|
||||
Change-Id: I82cfc396309b5ab2e8d6e9a87eda8ea7e3799473
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/823217
|
||||
Reviewed-by: Russ Cox <rsc@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/252179
|
||||
Run-TryBot: Filippo Valsorda <filippo@golang.org>
|
||||
TryBot-Result: Go Bot <gobot@golang.org>
|
||||
Reviewed-by: Katie Hockman <katie@golang.org>
|
||||
---
|
||||
src/net/http/cgi/child.go | 36 ++++++++++++------
|
||||
src/net/http/cgi/child_test.go | 58 +++++++++++++++++++++++++++++
|
||||
src/net/http/cgi/matryoshka_test.go | 8 +++-
|
||||
src/net/http/fcgi/child.go | 39 ++++++++++++++-----
|
||||
src/net/http/fcgi/fcgi_test.go | 52 ++++++++++++++++++++++++++
|
||||
5 files changed, 171 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/net/http/cgi/child.go b/src/net/http/cgi/child.go
|
||||
index cb140f8f2f..2b210ea4a1 100644
|
||||
--- a/src/net/http/cgi/child.go
|
||||
+++ b/src/net/http/cgi/child.go
|
||||
@@ -165,10 +165,12 @@ func Serve(handler http.Handler) error {
|
||||
}
|
||||
|
||||
type response struct {
|
||||
- req *http.Request
|
||||
- header http.Header
|
||||
- bufw *bufio.Writer
|
||||
- headerSent bool
|
||||
+ req *http.Request
|
||||
+ header http.Header
|
||||
+ code int
|
||||
+ wroteHeader bool
|
||||
+ wroteCGIHeader bool
|
||||
+ bufw *bufio.Writer
|
||||
}
|
||||
|
||||
func (r *response) Flush() {
|
||||
@@ -180,26 +182,38 @@ func (r *response) Header() http.Header {
|
||||
}
|
||||
|
||||
func (r *response) Write(p []byte) (n int, err error) {
|
||||
- if !r.headerSent {
|
||||
+ if !r.wroteHeader {
|
||||
r.WriteHeader(http.StatusOK)
|
||||
}
|
||||
+ if !r.wroteCGIHeader {
|
||||
+ r.writeCGIHeader(p)
|
||||
+ }
|
||||
return r.bufw.Write(p)
|
||||
}
|
||||
|
||||
func (r *response) WriteHeader(code int) {
|
||||
- if r.headerSent {
|
||||
+ if r.wroteHeader {
|
||||
// Note: explicitly using Stderr, as Stdout is our HTTP output.
|
||||
fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on request for %s", r.req.URL)
|
||||
return
|
||||
}
|
||||
- r.headerSent = true
|
||||
- fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code))
|
||||
+ r.wroteHeader = true
|
||||
+ r.code = code
|
||||
+}
|
||||
|
||||
- // Set a default Content-Type
|
||||
+// writeCGIHeader finalizes the header sent to the client and writes it to the output.
|
||||
+// p is not written by writeHeader, but is the first chunk of the body
|
||||
+// that will be written. It is sniffed for a Content-Type if none is
|
||||
+// set explicitly.
|
||||
+func (r *response) writeCGIHeader(p []byte) {
|
||||
+ if r.wroteCGIHeader {
|
||||
+ return
|
||||
+ }
|
||||
+ r.wroteCGIHeader = true
|
||||
+ fmt.Fprintf(r.bufw, "Status: %d %s\r\n", r.code, http.StatusText(r.code))
|
||||
if _, hasType := r.header["Content-Type"]; !hasType {
|
||||
- r.header.Add("Content-Type", "text/html; charset=utf-8")
|
||||
+ r.header.Set("Content-Type", http.DetectContentType(p))
|
||||
}
|
||||
-
|
||||
r.header.Write(r.bufw)
|
||||
r.bufw.WriteString("\r\n")
|
||||
r.bufw.Flush()
|
||||
diff --git a/src/net/http/cgi/child_test.go b/src/net/http/cgi/child_test.go
|
||||
index 14e0af475f..18cf789bd5 100644
|
||||
--- a/src/net/http/cgi/child_test.go
|
||||
+++ b/src/net/http/cgi/child_test.go
|
||||
@@ -7,6 +7,11 @@
|
||||
package cgi
|
||||
|
||||
import (
|
||||
+ "bufio"
|
||||
+ "bytes"
|
||||
+ "net/http"
|
||||
+ "net/http/httptest"
|
||||
+ "strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -148,3 +153,56 @@ func TestRequestWithoutRemotePort(t *testing.T) {
|
||||
t.Errorf("RemoteAddr: got %q; want %q", g, e)
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestResponse(t *testing.T) {
|
||||
+ var tests = []struct {
|
||||
+ name string
|
||||
+ body string
|
||||
+ wantCT string
|
||||
+ }{
|
||||
+ {
|
||||
+ name: "no body",
|
||||
+ wantCT: "text/plain; charset=utf-8",
|
||||
+ },
|
||||
+ {
|
||||
+ name: "html",
|
||||
+ body: "<html><head><title>test page</title></head><body>This is a body</body></html>",
|
||||
+ wantCT: "text/html; charset=utf-8",
|
||||
+ },
|
||||
+ {
|
||||
+ name: "text",
|
||||
+ body: strings.Repeat("gopher", 86),
|
||||
+ wantCT: "text/plain; charset=utf-8",
|
||||
+ },
|
||||
+ {
|
||||
+ name: "jpg",
|
||||
+ body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024),
|
||||
+ wantCT: "image/jpeg",
|
||||
+ },
|
||||
+ }
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ var buf bytes.Buffer
|
||||
+ resp := response{
|
||||
+ req: httptest.NewRequest("GET", "/", nil),
|
||||
+ header: http.Header{},
|
||||
+ bufw: bufio.NewWriter(&buf),
|
||||
+ }
|
||||
+ n, err := resp.Write([]byte(tt.body))
|
||||
+ if err != nil {
|
||||
+ t.Errorf("Write: unexpected %v", err)
|
||||
+ }
|
||||
+ if want := len(tt.body); n != want {
|
||||
+ t.Errorf("reported short Write: got %v want %v", n, want)
|
||||
+ }
|
||||
+ resp.writeCGIHeader(nil)
|
||||
+ resp.Flush()
|
||||
+ if got := resp.Header().Get("Content-Type"); got != tt.wantCT {
|
||||
+ t.Errorf("wrong content-type: got %q, want %q", got, tt.wantCT)
|
||||
+ }
|
||||
+ if !bytes.HasSuffix(buf.Bytes(), []byte(tt.body)) {
|
||||
+ t.Errorf("body was not correctly written")
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/net/http/cgi/matryoshka_test.go b/src/net/http/cgi/matryoshka_test.go
|
||||
index 32d59c09a3..41a27889f2 100644
|
||||
--- a/src/net/http/cgi/matryoshka_test.go
|
||||
+++ b/src/net/http/cgi/matryoshka_test.go
|
||||
@@ -16,7 +16,9 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
+ "net/url"
|
||||
"os"
|
||||
+ "strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -52,7 +54,7 @@ func TestHostingOurselves(t *testing.T) {
|
||||
}
|
||||
replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
|
||||
|
||||
- if expected, got := "text/html; charset=utf-8", replay.Header().Get("Content-Type"); got != expected {
|
||||
+ if expected, got := "text/plain; charset=utf-8", replay.Header().Get("Content-Type"); got != expected {
|
||||
t.Errorf("got a Content-Type of %q; expected %q", got, expected)
|
||||
}
|
||||
if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
|
||||
@@ -203,6 +205,10 @@ func TestBeChildCGIProcess(t *testing.T) {
|
||||
if req.FormValue("no-body") == "1" {
|
||||
return
|
||||
}
|
||||
+ if eb, ok := req.Form["exact-body"]; ok {
|
||||
+ io.WriteString(rw, eb[0])
|
||||
+ return
|
||||
+ }
|
||||
if req.FormValue("write-forever") == "1" {
|
||||
io.Copy(rw, neverEnding('a'))
|
||||
for {
|
||||
diff --git a/src/net/http/fcgi/child.go b/src/net/http/fcgi/child.go
|
||||
index 30a6b2ce2d..a31273b3ec 100644
|
||||
--- a/src/net/http/fcgi/child.go
|
||||
+++ b/src/net/http/fcgi/child.go
|
||||
@@ -74,10 +74,12 @@ func (r *request) parseParams() {
|
||||
|
||||
// response implements http.ResponseWriter.
|
||||
type response struct {
|
||||
- req *request
|
||||
- header http.Header
|
||||
- w *bufWriter
|
||||
- wroteHeader bool
|
||||
+ req *request
|
||||
+ header http.Header
|
||||
+ code int
|
||||
+ wroteHeader bool
|
||||
+ wroteCGIHeader bool
|
||||
+ w *bufWriter
|
||||
}
|
||||
|
||||
func newResponse(c *child, req *request) *response {
|
||||
@@ -92,11 +94,14 @@ func (r *response) Header() http.Header {
|
||||
return r.header
|
||||
}
|
||||
|
||||
-func (r *response) Write(data []byte) (int, error) {
|
||||
+func (r *response) Write(p []byte) (n int, err error) {
|
||||
if !r.wroteHeader {
|
||||
r.WriteHeader(http.StatusOK)
|
||||
}
|
||||
- return r.w.Write(data)
|
||||
+ if !r.wroteCGIHeader {
|
||||
+ r.writeCGIHeader(p)
|
||||
+ }
|
||||
+ return r.w.Write(p)
|
||||
}
|
||||
|
||||
func (r *response) WriteHeader(code int) {
|
||||
@@ -104,22 +109,34 @@ func (r *response) WriteHeader(code int) {
|
||||
return
|
||||
}
|
||||
r.wroteHeader = true
|
||||
+ r.code = code
|
||||
if code == http.StatusNotModified {
|
||||
// Must not have body.
|
||||
r.header.Del("Content-Type")
|
||||
r.header.Del("Content-Length")
|
||||
r.header.Del("Transfer-Encoding")
|
||||
- } else if r.header.Get("Content-Type") == "" {
|
||||
- r.header.Set("Content-Type", "text/html; charset=utf-8")
|
||||
}
|
||||
-
|
||||
if r.header.Get("Date") == "" {
|
||||
r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
|
||||
}
|
||||
+}
|
||||
|
||||
- fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code))
|
||||
+// writeCGIHeader finalizes the header sent to the client and writes it to the output.
|
||||
+// p is not written by writeHeader, but is the first chunk of the body
|
||||
+// that will be written. It is sniffed for a Content-Type if none is
|
||||
+// set explicitly.
|
||||
+func (r *response) writeCGIHeader(p []byte) {
|
||||
+ if r.wroteCGIHeader {
|
||||
+ return
|
||||
+ }
|
||||
+ r.wroteCGIHeader = true
|
||||
+ fmt.Fprintf(r.w, "Status: %d %s\r\n", r.code, http.StatusText(r.code))
|
||||
+ if _, hasType := r.header["Content-Type"]; r.code != http.StatusNotModified && !hasType {
|
||||
+ r.header.Set("Content-Type", http.DetectContentType(p))
|
||||
+ }
|
||||
r.header.Write(r.w)
|
||||
r.w.WriteString("\r\n")
|
||||
+ r.w.Flush()
|
||||
}
|
||||
|
||||
func (r *response) Flush() {
|
||||
@@ -290,6 +307,8 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) {
|
||||
httpReq = httpReq.WithContext(envVarCtx)
|
||||
c.handler.ServeHTTP(r, httpReq)
|
||||
}
|
||||
+ // Make sure we serve something even if nothing was written to r
|
||||
+ r.Write(nil)
|
||||
r.Close()
|
||||
c.mu.Lock()
|
||||
delete(c.requests, req.reqId)
|
||||
diff --git a/src/net/http/fcgi/fcgi_test.go b/src/net/http/fcgi/fcgi_test.go
|
||||
index e9d2b34023..4a27a12c35 100644
|
||||
--- a/src/net/http/fcgi/fcgi_test.go
|
||||
+++ b/src/net/http/fcgi/fcgi_test.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
+ "strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -344,3 +345,54 @@ func TestChildServeReadsEnvVars(t *testing.T) {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestResponseWriterSniffsContentType(t *testing.T) {
|
||||
+ var tests = []struct {
|
||||
+ name string
|
||||
+ body string
|
||||
+ wantCT string
|
||||
+ }{
|
||||
+ {
|
||||
+ name: "no body",
|
||||
+ wantCT: "text/plain; charset=utf-8",
|
||||
+ },
|
||||
+ {
|
||||
+ name: "html",
|
||||
+ body: "<html><head><title>test page</title></head><body>This is a body</body></html>",
|
||||
+ wantCT: "text/html; charset=utf-8",
|
||||
+ },
|
||||
+ {
|
||||
+ name: "text",
|
||||
+ body: strings.Repeat("gopher", 86),
|
||||
+ wantCT: "text/plain; charset=utf-8",
|
||||
+ },
|
||||
+ {
|
||||
+ name: "jpg",
|
||||
+ body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024),
|
||||
+ wantCT: "image/jpeg",
|
||||
+ },
|
||||
+ }
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ input := make([]byte, len(streamFullRequestStdin))
|
||||
+ copy(input, streamFullRequestStdin)
|
||||
+ rc := nopWriteCloser{bytes.NewBuffer(input)}
|
||||
+ done := make(chan bool)
|
||||
+ var resp *response
|
||||
+ c := newChild(rc, http.HandlerFunc(func(
|
||||
+ w http.ResponseWriter,
|
||||
+ r *http.Request,
|
||||
+ ) {
|
||||
+ io.WriteString(w, tt.body)
|
||||
+ resp = w.(*response)
|
||||
+ done <- true
|
||||
+ }))
|
||||
+ defer c.cleanUp()
|
||||
+ go c.serve()
|
||||
+ <-done
|
||||
+ if got := resp.Header().Get("Content-Type"); got != tt.wantCT {
|
||||
+ t.Errorf("got a Content-Type of %q; expected it to start with %q", got, tt.wantCT)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
413
0020-golang-fix-CVE-2020-28366.patch
Normal file
413
0020-golang-fix-CVE-2020-28366.patch
Normal file
@ -0,0 +1,413 @@
|
||||
From 24fb490f5c5ba855ad9feba179f820a835f68d66 Mon Sep 17 00:00:00 2001
|
||||
From: liuzekun <liuzekun@huawei.com>
|
||||
Date: Tue, 1 Dec 2020 22:50:08 -0500
|
||||
Subject: [PATCH] golang: fix CVE-2020-28366
|
||||
|
||||
Upstream: https://github.com/golang/go/commit/062e0e5ce6df339dc26732438ad771f73dbf2292
|
||||
cmd/go, cmd/cgo: don't let bogus symbol set cgo_ldflag
|
||||
|
||||
A hand-edited object file can have a symbol name that uses newline and
|
||||
other normally invalid characters. The cgo tool will generate Go files
|
||||
containing symbol names, unquoted. That can permit those symbol names
|
||||
to inject Go code into a cgo-generated file. If that Go code uses the
|
||||
//go:cgo_ldflag pragma, it can cause the C linker to run arbitrary
|
||||
code when building a package. If you build an imported package we
|
||||
permit arbitrary code at run time, but we don't want to permit it at
|
||||
package build time. This CL prevents this in two ways.
|
||||
|
||||
In cgo, reject invalid symbols that contain non-printable or space
|
||||
characters, or that contain anything that looks like a Go comment.
|
||||
|
||||
In the go tool, double check all //go:cgo_ldflag directives in
|
||||
generated code, to make sure they follow the existing LDFLAG restrictions.
|
||||
|
||||
Thanks to Imre Rad / https://www.linkedin.com/in/imre-rad-2358749b for
|
||||
reporting this.
|
||||
|
||||
Fixes CVE-2020-28367
|
||||
|
||||
Change-Id: Ia1ad8f3791ea79612690fa7d26ac451d0f6df7c1
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/895832
|
||||
Reviewed-by: Than McIntosh <thanm@google.com>
|
||||
Reviewed-by: Cherry Zhang <cherryyz@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/269658
|
||||
Trust: Katie Hockman <katie@golang.org>
|
||||
Trust: Roland Shoemaker <roland@golang.org>
|
||||
Run-TryBot: Katie Hockman <katie@golang.org>
|
||||
TryBot-Result: Go Bot <gobot@golang.org>
|
||||
Reviewed-by: Roland Shoemaker <roland@golang.org>
|
||||
|
||||
Signed-off-by: liuzekun <liuzekun@huawei.com>
|
||||
---
|
||||
misc/cgo/errors/badsym_test.go | 216 +++++++++++++++++++++++++++++++
|
||||
src/cmd/cgo/out.go | 24 ++++
|
||||
src/cmd/go/internal/work/exec.go | 60 +++++++++
|
||||
3 files changed, 300 insertions(+)
|
||||
create mode 100644 misc/cgo/errors/badsym_test.go
|
||||
|
||||
diff --git a/misc/cgo/errors/badsym_test.go b/misc/cgo/errors/badsym_test.go
|
||||
new file mode 100644
|
||||
index 0000000..b2701bf
|
||||
--- /dev/null
|
||||
+++ b/misc/cgo/errors/badsym_test.go
|
||||
@@ -0,0 +1,216 @@
|
||||
+// Copyright 2020 The Go Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style
|
||||
+// license that can be found in the LICENSE file.
|
||||
+
|
||||
+package errorstest
|
||||
+
|
||||
+import (
|
||||
+ "bytes"
|
||||
+ "io/ioutil"
|
||||
+ "os"
|
||||
+ "os/exec"
|
||||
+ "path/filepath"
|
||||
+ "strings"
|
||||
+ "testing"
|
||||
+ "unicode"
|
||||
+)
|
||||
+
|
||||
+// A manually modified object file could pass unexpected characters
|
||||
+// into the files generated by cgo.
|
||||
+
|
||||
+const magicInput = "abcdefghijklmnopqrstuvwxyz0123"
|
||||
+const magicReplace = "\n//go:cgo_ldflag \"-badflag\"\n//"
|
||||
+
|
||||
+const cSymbol = "BadSymbol" + magicInput + "Name"
|
||||
+const cDefSource = "int " + cSymbol + " = 1;"
|
||||
+const cRefSource = "extern int " + cSymbol + "; int F() { return " + cSymbol + "; }"
|
||||
+
|
||||
+// goSource is the source code for the trivial Go file we use.
|
||||
+// We will replace TMPDIR with the temporary directory name.
|
||||
+const goSource = `
|
||||
+package main
|
||||
+
|
||||
+// #cgo LDFLAGS: TMPDIR/cbad.o TMPDIR/cbad.so
|
||||
+// extern int F();
|
||||
+import "C"
|
||||
+
|
||||
+func main() {
|
||||
+ println(C.F())
|
||||
+}
|
||||
+`
|
||||
+
|
||||
+func TestBadSymbol(t *testing.T) {
|
||||
+ dir := t.TempDir()
|
||||
+
|
||||
+ mkdir := func(base string) string {
|
||||
+ ret := filepath.Join(dir, base)
|
||||
+ if err := os.Mkdir(ret, 0755); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ return ret
|
||||
+ }
|
||||
+
|
||||
+ cdir := mkdir("c")
|
||||
+ godir := mkdir("go")
|
||||
+
|
||||
+ makeFile := func(mdir, base, source string) string {
|
||||
+ ret := filepath.Join(mdir, base)
|
||||
+ if err := ioutil.WriteFile(ret, []byte(source), 0644); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ return ret
|
||||
+ }
|
||||
+
|
||||
+ cDefFile := makeFile(cdir, "cdef.c", cDefSource)
|
||||
+ cRefFile := makeFile(cdir, "cref.c", cRefSource)
|
||||
+
|
||||
+ ccCmd := cCompilerCmd(t)
|
||||
+
|
||||
+ cCompile := func(arg, base, src string) string {
|
||||
+ out := filepath.Join(cdir, base)
|
||||
+ run := append(ccCmd, arg, "-o", out, src)
|
||||
+ output, err := exec.Command(run[0], run[1:]...).CombinedOutput()
|
||||
+ if err != nil {
|
||||
+ t.Log(run)
|
||||
+ t.Logf("%s", output)
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ if err := os.Remove(src); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ return out
|
||||
+ }
|
||||
+
|
||||
+ // Build a shared library that defines a symbol whose name
|
||||
+ // contains magicInput.
|
||||
+
|
||||
+ cShared := cCompile("-shared", "c.so", cDefFile)
|
||||
+
|
||||
+ // Build an object file that refers to the symbol whose name
|
||||
+ // contains magicInput.
|
||||
+
|
||||
+ cObj := cCompile("-c", "c.o", cRefFile)
|
||||
+
|
||||
+ // Rewrite the shared library and the object file, replacing
|
||||
+ // magicInput with magicReplace. This will have the effect of
|
||||
+ // introducing a symbol whose name looks like a cgo command.
|
||||
+ // The cgo tool will use that name when it generates the
|
||||
+ // _cgo_import.go file, thus smuggling a magic //go:cgo_ldflag
|
||||
+ // pragma into a Go file. We used to not check the pragmas in
|
||||
+ // _cgo_import.go.
|
||||
+
|
||||
+ rewrite := func(from, to string) {
|
||||
+ obj, err := ioutil.ReadFile(from)
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+
|
||||
+ if bytes.Count(obj, []byte(magicInput)) == 0 {
|
||||
+ t.Fatalf("%s: did not find magic string", from)
|
||||
+ }
|
||||
+
|
||||
+ if len(magicInput) != len(magicReplace) {
|
||||
+ t.Fatalf("internal test error: different magic lengths: %d != %d", len(magicInput), len(magicReplace))
|
||||
+ }
|
||||
+
|
||||
+ obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace))
|
||||
+
|
||||
+ if err := ioutil.WriteFile(to, obj, 0644); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cBadShared := filepath.Join(godir, "cbad.so")
|
||||
+ rewrite(cShared, cBadShared)
|
||||
+
|
||||
+ cBadObj := filepath.Join(godir, "cbad.o")
|
||||
+ rewrite(cObj, cBadObj)
|
||||
+
|
||||
+ goSourceBadObject := strings.ReplaceAll(goSource, "TMPDIR", godir)
|
||||
+ makeFile(godir, "go.go", goSourceBadObject)
|
||||
+
|
||||
+ makeFile(godir, "go.mod", "module badsym")
|
||||
+
|
||||
+ // Try to build our little package.
|
||||
+ cmd := exec.Command("go", "build", "-ldflags=-v")
|
||||
+ cmd.Dir = godir
|
||||
+ output, err := cmd.CombinedOutput()
|
||||
+
|
||||
+ // The build should fail, but we want it to fail because we
|
||||
+ // detected the error, not because we passed a bad flag to the
|
||||
+ // C linker.
|
||||
+
|
||||
+ if err == nil {
|
||||
+ t.Errorf("go build succeeded unexpectedly")
|
||||
+ }
|
||||
+
|
||||
+ t.Logf("%s", output)
|
||||
+
|
||||
+ for _, line := range bytes.Split(output, []byte("\n")) {
|
||||
+ if bytes.Contains(line, []byte("dynamic symbol")) && bytes.Contains(line, []byte("contains unsupported character")) {
|
||||
+ // This is the error from cgo.
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ // We passed -ldflags=-v to see the external linker invocation,
|
||||
+ // which should not include -badflag.
|
||||
+ if bytes.Contains(line, []byte("-badflag")) {
|
||||
+ t.Error("output should not mention -badflag")
|
||||
+ }
|
||||
+
|
||||
+ // Also check for compiler errors, just in case.
|
||||
+ // GCC says "unrecognized command line option".
|
||||
+ // clang says "unknown argument".
|
||||
+ if bytes.Contains(line, []byte("unrecognized")) || bytes.Contains(output, []byte("unknown")) {
|
||||
+ t.Error("problem should have been caught before invoking C linker")
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func cCompilerCmd(t *testing.T) []string {
|
||||
+ cc := []string{goEnv(t, "CC")}
|
||||
+
|
||||
+ out := goEnv(t, "GOGCCFLAGS")
|
||||
+ quote := '\000'
|
||||
+ start := 0
|
||||
+ lastSpace := true
|
||||
+ backslash := false
|
||||
+ s := string(out)
|
||||
+ for i, c := range s {
|
||||
+ if quote == '\000' && unicode.IsSpace(c) {
|
||||
+ if !lastSpace {
|
||||
+ cc = append(cc, s[start:i])
|
||||
+ lastSpace = true
|
||||
+ }
|
||||
+ } else {
|
||||
+ if lastSpace {
|
||||
+ start = i
|
||||
+ lastSpace = false
|
||||
+ }
|
||||
+ if quote == '\000' && !backslash && (c == '"' || c == '\'') {
|
||||
+ quote = c
|
||||
+ backslash = false
|
||||
+ } else if !backslash && quote == c {
|
||||
+ quote = '\000'
|
||||
+ } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
|
||||
+ backslash = true
|
||||
+ } else {
|
||||
+ backslash = false
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if !lastSpace {
|
||||
+ cc = append(cc, s[start:])
|
||||
+ }
|
||||
+ return cc
|
||||
+}
|
||||
+
|
||||
+func goEnv(t *testing.T, key string) string {
|
||||
+ out, err := exec.Command("go", "env", key).CombinedOutput()
|
||||
+ if err != nil {
|
||||
+ t.Logf("go env %s\n", key)
|
||||
+ t.Logf("%s", out)
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ return strings.TrimSpace(string(out))
|
||||
+}
|
||||
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
|
||||
index 1fddbb6..65a8d66 100644
|
||||
--- a/src/cmd/cgo/out.go
|
||||
+++ b/src/cmd/cgo/out.go
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
+ "unicode"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -325,6 +326,8 @@ func dynimport(obj string) {
|
||||
if s.Version != "" {
|
||||
targ += "#" + s.Version
|
||||
}
|
||||
+ checkImportSymName(s.Name)
|
||||
+ checkImportSymName(targ)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
|
||||
}
|
||||
lib, _ := f.ImportedLibraries()
|
||||
@@ -340,6 +343,7 @@ func dynimport(obj string) {
|
||||
if len(s) > 0 && s[0] == '_' {
|
||||
s = s[1:]
|
||||
}
|
||||
+ checkImportSymName(s)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
|
||||
}
|
||||
lib, _ := f.ImportedLibraries()
|
||||
@@ -354,6 +358,8 @@ func dynimport(obj string) {
|
||||
for _, s := range sym {
|
||||
ss := strings.Split(s, ":")
|
||||
name := strings.Split(ss[0], "@")[0]
|
||||
+ checkImportSymName(name)
|
||||
+ checkImportSymName(ss[0])
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
|
||||
}
|
||||
return
|
||||
@@ -371,6 +377,7 @@ func dynimport(obj string) {
|
||||
// Go symbols.
|
||||
continue
|
||||
}
|
||||
+ checkImportSymName(s.Name)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, s.Name, s.Library)
|
||||
}
|
||||
lib, err := f.ImportedLibraries()
|
||||
@@ -386,6 +393,23 @@ func dynimport(obj string) {
|
||||
fatalf("cannot parse %s as ELF, Mach-O, PE or XCOFF", obj)
|
||||
}
|
||||
|
||||
+// checkImportSymName checks a symbol name we are going to emit as part
|
||||
+// of a //go:cgo_import_dynamic pragma. These names come from object
|
||||
+// files, so they may be corrupt. We are going to emit them unquoted,
|
||||
+// so while they don't need to be valid symbol names (and in some cases,
|
||||
+// involving symbol versions, they won't be) they must contain only
|
||||
+// graphic characters and must not contain Go comments.
|
||||
+func checkImportSymName(s string) {
|
||||
+ for _, c := range s {
|
||||
+ if !unicode.IsGraphic(c) || unicode.IsSpace(c) {
|
||||
+ fatalf("dynamic symbol %q contains unsupported character", s)
|
||||
+ }
|
||||
+ }
|
||||
+ if strings.Index(s, "//") >= 0 || strings.Index(s, "/*") >= 0 {
|
||||
+ fatalf("dynamic symbol %q contains Go comment")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// Construct a gcc struct matching the gc argument frame.
|
||||
// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
|
||||
// These assumptions are checked by the gccProlog.
|
||||
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
|
||||
index 7dd9a90..0e5c34f 100644
|
||||
--- a/src/cmd/go/internal/work/exec.go
|
||||
+++ b/src/cmd/go/internal/work/exec.go
|
||||
@@ -2630,6 +2630,66 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
|
||||
noCompiler()
|
||||
}
|
||||
|
||||
+ // Double check the //go:cgo_ldflag comments in the generated files.
|
||||
+ // The compiler only permits such comments in files whose base name
|
||||
+ // starts with "_cgo_". Make sure that the comments in those files
|
||||
+ // are safe. This is a backstop against people somehow smuggling
|
||||
+ // such a comment into a file generated by cgo.
|
||||
+ if cfg.BuildToolchainName == "gc" && !cfg.BuildN {
|
||||
+ var flags []string
|
||||
+ for _, f := range outGo {
|
||||
+ if !strings.HasPrefix(filepath.Base(f), "_cgo_") {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ src, err := ioutil.ReadFile(f)
|
||||
+ if err != nil {
|
||||
+ return nil, nil, err
|
||||
+ }
|
||||
+
|
||||
+ const cgoLdflag = "//go:cgo_ldflag"
|
||||
+ idx := bytes.Index(src, []byte(cgoLdflag))
|
||||
+ for idx >= 0 {
|
||||
+ // We are looking at //go:cgo_ldflag.
|
||||
+ // Find start of line.
|
||||
+ start := bytes.LastIndex(src[:idx], []byte("\n"))
|
||||
+ if start == -1 {
|
||||
+ start = 0
|
||||
+ }
|
||||
+
|
||||
+ // Find end of line.
|
||||
+ end := bytes.Index(src[idx:], []byte("\n"))
|
||||
+ if end == -1 {
|
||||
+ end = len(src)
|
||||
+ } else {
|
||||
+ end += idx
|
||||
+ }
|
||||
+
|
||||
+ // Check for first line comment in line.
|
||||
+ // We don't worry about /* */ comments,
|
||||
+ // which normally won't appear in files
|
||||
+ // generated by cgo.
|
||||
+ commentStart := bytes.Index(src[start:], []byte("//"))
|
||||
+ commentStart += start
|
||||
+ // If that line comment is //go:cgo_ldflag,
|
||||
+ // it's a match.
|
||||
+ if bytes.HasPrefix(src[commentStart:], []byte(cgoLdflag)) {
|
||||
+ // Pull out the flag, and unquote it.
|
||||
+ // This is what the compiler does.
|
||||
+ flag := string(src[idx+len(cgoLdflag) : end])
|
||||
+ flag = strings.TrimSpace(flag)
|
||||
+ flag = strings.Trim(flag, `"`)
|
||||
+ flags = append(flags, flag)
|
||||
+ }
|
||||
+ src = src[end:]
|
||||
+ idx = bytes.Index(src, []byte(cgoLdflag))
|
||||
+ }
|
||||
+ }
|
||||
+ if err := checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags); err != nil {
|
||||
+ return nil, nil, err
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return outGo, outObj, nil
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
67
0021-golang-fix-CVE-2020-28367.patch
Normal file
67
0021-golang-fix-CVE-2020-28367.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From ac9a264a575bbbc9de2374a65a6c8fd50c32000d Mon Sep 17 00:00:00 2001
|
||||
From: liuzekun <liuzekun@huawei.com>
|
||||
Date: Mon, 30 Nov 2020 22:18:43 -0500
|
||||
Subject: [PATCH] golang: fix CVE-2020-28367
|
||||
|
||||
Upstream: https://github.com/golang/go/commit/da7aa86917811a571e6634b45a457f918b8e6561
|
||||
cmd/go: in cgoflags, permit -DX1, prohibit -Wp,-D,opt
|
||||
|
||||
Restrict -D and -U to ASCII C identifiers, but do permit trailing digits.
|
||||
When using -Wp, prohibit commas in -D values.
|
||||
|
||||
Change-Id: Ibfc4dfdd6e6c258e131448e7682610c44eee9492
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/267277
|
||||
Trust: Ian Lance Taylor <iant@golang.org>
|
||||
Run-TryBot: Ian Lance Taylor <iant@golang.org>
|
||||
TryBot-Result: Go Bot <gobot@golang.org>
|
||||
Reviewed-by: Bryan C. Mills <bcmills@google.com>
|
||||
---
|
||||
src/cmd/go/internal/work/security.go | 4 ++--
|
||||
src/cmd/go/internal/work/security_test.go | 2 ++
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go
|
||||
index 0d8da21..b00c21e 100644
|
||||
--- a/src/cmd/go/internal/work/security.go
|
||||
+++ b/src/cmd/go/internal/work/security.go
|
||||
@@ -42,7 +42,7 @@ import (
|
||||
var re = lazyregexp.New
|
||||
|
||||
var validCompilerFlags = []*lazyregexp.Regexp{
|
||||
- re(`-D([A-Za-z_].*)`),
|
||||
+ re(`-D([A-Za-z_][A-Za-z0-9_]*)(=[^@\-]*)?`),
|
||||
re(`-F([^@\-].*)`),
|
||||
re(`-I([^@\-].*)`),
|
||||
re(`-O`),
|
||||
@@ -50,7 +50,7 @@ var validCompilerFlags = []*lazyregexp.Regexp{
|
||||
re(`-W`),
|
||||
re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
|
||||
re(`-Wa,-mbig-obj`),
|
||||
- re(`-Wp,-D([A-Za-z_].*)`),
|
||||
+ re(`-Wp,-D([A-Za-z_][A-Za-z0-9_]*)(=[^@,\-]*)?`),
|
||||
re(`-ansi`),
|
||||
re(`-f(no-)?asynchronous-unwind-tables`),
|
||||
re(`-f(no-)?blocks`),
|
||||
diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go
|
||||
index fd8caea..eac029d 100644
|
||||
--- a/src/cmd/go/internal/work/security_test.go
|
||||
+++ b/src/cmd/go/internal/work/security_test.go
|
||||
@@ -21,6 +21,7 @@ var goodCompilerFlags = [][]string{
|
||||
{"-Osmall"},
|
||||
{"-W"},
|
||||
{"-Wall"},
|
||||
+ {"-Wp,-Dfoo1"},
|
||||
{"-fobjc-arc"},
|
||||
{"-fno-objc-arc"},
|
||||
{"-fomit-frame-pointer"},
|
||||
@@ -70,6 +71,7 @@ var badCompilerFlags = [][]string{
|
||||
{"-I-dir"},
|
||||
{"-O@1"},
|
||||
{"-Wa,-foo"},
|
||||
+ {"-Wp,-DX,-D@X"},
|
||||
{"-W@foo"},
|
||||
{"-g@gdb"},
|
||||
{"-g-gdb"},
|
||||
--
|
||||
2.19.1
|
||||
|
||||
118
0022-fix-CVE-2020-29509-CVE-2020-29511.patch
Normal file
118
0022-fix-CVE-2020-29509-CVE-2020-29511.patch
Normal file
@ -0,0 +1,118 @@
|
||||
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
|
||||
|
||||
62
0023-fix-CVE-2020-29510.patch
Normal file
62
0023-fix-CVE-2020-29510.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From e2710c3983b3249ba30f2d21802c984aef5fb163 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 23 Dec 2020 16:03:15 +0800
|
||||
Subject: [PATCH 2/2] encoding/xml: replace comments inside directives with a
|
||||
space
|
||||
|
||||
A Directive (like <!ENTITY xxx []>) can't have other nodes nested inside
|
||||
it (in our data structure representation), so there is no way to
|
||||
preserve comments. The previous behavior was to just elide them, which
|
||||
however might change the semantic meaning of the surrounding markup.
|
||||
Instead, replace them with a space which hopefully has the same semantic
|
||||
effect of the comment.
|
||||
|
||||
Directives are not actually a node type in the XML spec, which instead
|
||||
specifies each of them separately (<!ENTITY, <!DOCTYPE, etc.), each with
|
||||
its own grammar. The rules for where and when the comments are allowed
|
||||
are not straightforward, and can't be implemented without implementing
|
||||
custom logic for each of the directives.
|
||||
|
||||
Simply preserving the comments in the body of the directive would be
|
||||
problematic, as there can be unmatched quotes inside the comment.
|
||||
Whether those quotes are considered meaningful semantically or not,
|
||||
other parsers might disagree and interpret the output differently.
|
||||
|
||||
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-29510
|
||||
Updates #43168
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/277893/1
|
||||
Change-Id: Icd86c75beff3e1e0689543efebdad10ed5178ce3
|
||||
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
src/encoding/xml/xml.go | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go
|
||||
index 073ceee1b2..3746018613 100644
|
||||
--- a/src/encoding/xml/xml.go
|
||||
+++ b/src/encoding/xml/xml.go
|
||||
@@ -764,6 +764,12 @@ func (d *Decoder) rawToken() (Token, error) {
|
||||
}
|
||||
b0, b1 = b1, b
|
||||
}
|
||||
+
|
||||
+ // Replace the comment with a space in the returned Directive
|
||||
+ // body, so that markup parts that were separated by the comment
|
||||
+ // (like a "<" and a "!") don't get joined when re-encoding the
|
||||
+ // Directive, taking new semantic meaning.
|
||||
+ d.buf.WriteByte(' ')
|
||||
}
|
||||
}
|
||||
return Directive(d.buf.Bytes()), nil
|
||||
--
|
||||
2.17.1
|
||||
|
||||
14
golang.spec
14
golang.spec
@ -62,7 +62,7 @@
|
||||
|
||||
Name: golang
|
||||
Version: 1.13.15
|
||||
Release: 1
|
||||
Release: 2
|
||||
Summary: The Go Programming Language
|
||||
License: BSD and Public Domain
|
||||
URL: https://golang.org/
|
||||
@ -156,7 +156,12 @@ Patch6005: 0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch
|
||||
Patch6006: 0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch
|
||||
Patch6007: 0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch
|
||||
Patch6008: 0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch
|
||||
Patch6014: 0013-drop-hard-code-cert.patch
|
||||
Patch6013: 0013-drop-hard-code-cert.patch
|
||||
Patch6019: 0019-net-http-cgi-net-http-fcgi-add-Content-Type-detectio.patch
|
||||
Patch6020: 0020-golang-fix-CVE-2020-28366.patch
|
||||
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
|
||||
|
||||
ExclusiveArch: %{golang_arches}
|
||||
|
||||
@ -390,7 +395,10 @@ fi
|
||||
%files devel -f go-tests.list -f go-misc.list -f go-src.list
|
||||
|
||||
%changelog
|
||||
* Tue Aug 18 xiadanni <xiadanni1@huawei.com> - 1.13.15-1
|
||||
* Mon Jan 18 2021 jingrui<jingrui@huawei.com> - 1.13.15-2
|
||||
- sync cve fix
|
||||
|
||||
* Tue Aug 18 2020 xiadanni <xiadanni1@huawei.com> - 1.13.15-1
|
||||
- upgrade to 1.13.15
|
||||
|
||||
* Tue May 12 2020 lixiang <lixiang172@huawei.com> - 1.13.6
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user