From d66b2112bd076e29349e1060e812a211a8fa9c32 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Fri, 19 Feb 2021 10:34:55 -0500 Subject: [release-branch.go1.16] go/internal/gccgoimporter: fix up gccgo installation test Change the TestInstallationImporter testpoint to query type information for sort.Search instead of sort.Ints. The latter function changed recently (1.16 timeframe), parameter "a" is now "x". A better candidate for this sort of query is sort.Search, which has been stable for a while. Fixes #47610. Change-Id: I314476eac0b0802f86f5cbce32195cab2926db83 Reviewed-on: https://go-review.googlesource.com/c/go/+/294290 Trust: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor (cherry picked from commit 0f66fb7b856b02497cf801ce72d80f375f53358b) Reviewed-on: https://go-review.googlesource.com/c/go/+/340952 --- src/go/internal/gccgoimporter/gccgoinstallation_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/internal/gccgoimporter/gccgoinstallation_test.go b/src/go/internal/gccgoimporter/gccgoinstallation_test.go index b332babc7b..df0188ace7 100644 --- a/src/go/internal/gccgoimporter/gccgoinstallation_test.go +++ b/src/go/internal/gccgoimporter/gccgoinstallation_test.go @@ -184,7 +184,7 @@ func TestInstallationImporter(t *testing.T) { {pkgpath: "io", name: "ReadWriter", want: "type ReadWriter interface{Reader; Writer}"}, {pkgpath: "math", name: "Pi", want: "const Pi untyped float"}, {pkgpath: "math", name: "Sin", want: "func Sin(x float64) float64"}, - {pkgpath: "sort", name: "Ints", want: "func Ints(a []int)"}, + {pkgpath: "sort", name: "Search", want: "func Search(n int, f func(int) bool) int"}, {pkgpath: "unsafe", name: "Pointer", want: "type Pointer"}, } { runImporterTest(t, imp, nil, &test) -- cgit v1.2.3-54-g00ecf From 0d530843be0021aa56771c2f922e952beb190d97 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 12 Aug 2021 17:17:51 -0400 Subject: [release-branch.go1.16] runtime: drop SIGPROF while in ARM < 7 kernel helpers On Linux ARMv6 and below runtime/internal/atomic.Cas calls into a kernel cas helper at a fixed address. If a SIGPROF arrives while executing the kernel helper, the sigprof lostAtomic logic will miss that we are potentially in the spinlock critical section, which could cause a deadlock when using atomics later in sigprof. For #47505 Fixes #47675 Change-Id: If8ba0d0fc47e45d4e6c68eca98fac4c6ed4e43c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/341889 Trust: Michael Pratt Run-TryBot: Michael Pratt Reviewed-by: Michael Knyszek Reviewed-by: Cherry Mui TryBot-Result: Go Bot (cherry picked from commit 20a620fd9f7bc35739c1af3602d53808d0430814) Reviewed-on: https://go-review.googlesource.com/c/go/+/341853 --- src/runtime/proc.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 3ace2b329b..32fe877041 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4425,7 +4425,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { return } - // On mips{,le}, 64bit atomics are emulated with spinlocks, in + // On mips{,le}/arm, 64bit atomics are emulated with spinlocks, in // runtime/internal/atomic. If SIGPROF arrives while the program is inside // the critical section, it creates a deadlock (when writing the sample). // As a workaround, create a counter of SIGPROFs while in critical section @@ -4438,6 +4438,13 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { return } } + if GOARCH == "arm" && goarm < 7 && GOOS == "linux" && pc&0xffff0000 == 0xffff0000 { + // runtime/internal/atomic functions call into kernel + // helpers on arm < 7. See + // runtime/internal/atomic/sys_linux_arm.s. + cpuprof.lostAtomic++ + return + } } // Profiling runs concurrently with GC, so it must not allocate. -- cgit v1.2.3-54-g00ecf From 6c480017ae600b2c90a264a922e041df04dfa785 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 18 Aug 2021 11:49:29 -0700 Subject: [release-branch.go1.16] archive/zip: prevent preallocation check from overflowing If the indicated directory size in the archive header is so large that subtracting it from the archive size overflows a uint64, the check that the indicated number of files in the archive can be effectively bypassed. Prevent this from happening by checking that the indicated directory size is less than the size of the archive. Thanks to the OSS-Fuzz project for discovering this issue and to Emmanuel Odeke for reporting it. Fixes #47985 Updates #47801 Fixes CVE-2021-39293 Change-Id: Ifade26b98a40f3b37398ca86bd5252d12394dd24 Reviewed-on: https://go-review.googlesource.com/c/go/+/343434 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Russ Cox (cherry picked from commit bacbc33439b124ffd7392c91a5f5d96eca8c0c0b) Reviewed-on: https://go-review.googlesource.com/c/go/+/345409 Reviewed-by: Emmanuel Odeke Run-TryBot: Emmanuel Odeke Trust: Cherry Mui --- src/archive/zip/reader.go | 2 +- src/archive/zip/reader_test.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index ddef2b7b5a..801d1313b6 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -105,7 +105,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error { // indicate it contains up to 1 << 128 - 1 files. Since each file has a // header which will be _at least_ 30 bytes we can safely preallocate // if (data size / 30) >= end.directoryRecords. - if (uint64(size)-end.directorySize)/30 >= end.directoryRecords { + if end.directorySize < uint64(size) && (uint64(size)-end.directorySize)/30 >= end.directoryRecords { z.File = make([]*File, 0, end.directoryRecords) } z.Comment = end.comment diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index 471be27bb1..99f13345d8 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -1225,3 +1225,21 @@ func TestCVE202133196(t *testing.T) { t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File)) } } + +func TestCVE202139293(t *testing.T) { + // directory size is so large, that the check in Reader.init + // overflows when subtracting from the archive size, causing + // the pre-allocation check to be bypassed. + data := []byte{ + 0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b, + 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b, + 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff, + } + _, err := NewReader(bytes.NewReader(data), int64(len(data))) + if err != ErrFormat { + t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat) + } +} -- cgit v1.2.3-54-g00ecf From 8226cb06aa44449a1b2f65dcfe87c4e9e2c45dbf Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Wed, 1 Sep 2021 12:59:25 -0700 Subject: [release-branch.go1.16] all: update golang.org/x/net to pull in CL 346890 For #47691. Change-Id: I6650fdfc78786fc47a54167bf2f9061422bbb343 Reviewed-on: https://go-review.googlesource.com/c/go/+/347031 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/go.mod | 2 +- src/go.sum | 4 ++-- src/net/http/h2_bundle.go | 9 +++++++++ src/vendor/modules.txt | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/go.mod b/src/go.mod index 798677b68c..17fc3648a3 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b + golang.org/x/net v0.0.0-20210901185431-d2e9a4ea682f golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/text v0.3.4 // indirect ) diff --git a/src/go.sum b/src/go.sum index f38b3c36f0..cea3ab4134 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,8 +2,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b h1:SQCMv1JDt7RN/Vp0bjtNMSufVVHgpFVzmDFdCLL31yY= -golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210901185431-d2e9a4ea682f h1:pkBhRt1hlsctT9xYRDknb4y+e/yiacRWlnft5a4QH8Y= +golang.org/x/net v0.0.0-20210901185431-d2e9a4ea682f/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 6bef310feb..22f1e78498 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -4435,6 +4435,15 @@ func (sc *http2serverConn) serve() { case res := <-sc.wroteFrameCh: sc.wroteFrame(res) case res := <-sc.readFrameCh: + // Process any written frames before reading new frames from the client since a + // written frame could have triggered a new stream to be started. + if sc.writingFrameAsync { + select { + case wroteRes := <-sc.wroteFrameCh: + sc.wroteFrame(wroteRes) + default: + } + } if !sc.processFrameFromReader(res) { return } diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index b18d36639a..061e0acb59 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519 golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -# golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b +# golang.org/x/net v0.0.0-20210901185431-d2e9a4ea682f ## explicit golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts -- cgit v1.2.3-54-g00ecf From 021fc241c968d328559db8342549c52b9f91c967 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 3 May 2021 16:32:52 -0700 Subject: [release-branch.go1.16] text/template: add lock for Template.tmpl to fix data race This adds a new lock protecting "tmpl". This is a copy of https://golang.org/cl/257817 by Andreas Fleig, updated for current tip, and updated to start running the html/template TestEscapeRace test. Thanks to @bep for providing the test case. For #39807 Fixes #47042 Change-Id: Ic8874484290283a49116812eeaffb8608346dc70 Reviewed-on: https://go-review.googlesource.com/c/go/+/316669 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov (cherry picked from commit 496d7c691481966fd6ea806205aa025698a172af) Reviewed-on: https://go-review.googlesource.com/c/go/+/348580 Reviewed-by: Emmanuel Odeke --- src/html/template/exec_test.go | 2 -- src/text/template/exec.go | 9 ++++----- src/text/template/exec_test.go | 38 ++++++++++++++++++++++++++++++++++++++ src/text/template/template.go | 9 +++++++++ 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/html/template/exec_test.go b/src/html/template/exec_test.go index 7d1bef1782..888587335d 100644 --- a/src/html/template/exec_test.go +++ b/src/html/template/exec_test.go @@ -1720,8 +1720,6 @@ var v = "v"; ` func TestEscapeRace(t *testing.T) { - t.Skip("this test currently fails with -race; see issue #39807") - tmpl := New("") _, err := tmpl.New("templ.html").Parse(raceText) if err != nil { diff --git a/src/text/template/exec.go b/src/text/template/exec.go index 19154fc640..ba01a15b22 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -179,10 +179,7 @@ func errRecover(errp *error) { // A template may be executed safely in parallel, although if parallel // executions share a Writer the output may be interleaved. func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { - var tmpl *Template - if t.common != nil { - tmpl = t.tmpl[name] - } + tmpl := t.Lookup(name) if tmpl == nil { return fmt.Errorf("template: no template %q associated with template %q", name, t.name) } @@ -230,6 +227,8 @@ func (t *Template) DefinedTemplates() string { return "" } var b strings.Builder + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() for name, tmpl := range t.tmpl { if tmpl.Tree == nil || tmpl.Root == nil { continue @@ -401,7 +400,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) { s.at(t) - tmpl := s.tmpl.tmpl[t.Name] + tmpl := s.tmpl.Lookup(t.Name) if tmpl == nil { s.errorf("template %q not defined", t.Name) } diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 1a129ed5af..78abc25d65 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -12,6 +12,7 @@ import ( "io" "reflect" "strings" + "sync" "testing" ) @@ -1710,3 +1711,40 @@ func TestIssue43065(t *testing.T) { t.Errorf("%s", err) } } + +// Issue 39807: data race in html/template & text/template +func TestIssue39807(t *testing.T) { + var wg sync.WaitGroup + + tplFoo, err := New("foo").Parse(`{{ template "bar" . }}`) + if err != nil { + t.Error(err) + } + + tplBar, err := New("bar").Parse("bar") + if err != nil { + t.Error(err) + } + + gofuncs := 10 + numTemplates := 10 + + for i := 1; i <= gofuncs; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 0; j < numTemplates; j++ { + _, err := tplFoo.AddParseTree(tplBar.Name(), tplBar.Tree) + if err != nil { + t.Error(err) + } + err = tplFoo.Execute(io.Discard, nil) + if err != nil { + t.Error(err) + } + } + }() + } + + wg.Wait() +} diff --git a/src/text/template/template.go b/src/text/template/template.go index ec26eb4c50..fd74d45e9b 100644 --- a/src/text/template/template.go +++ b/src/text/template/template.go @@ -13,6 +13,7 @@ import ( // common holds the information shared by related templates. type common struct { tmpl map[string]*Template // Map from name to defined templates. + muTmpl sync.RWMutex // protects tmpl option option // We use two maps, one for parsing and one for execution. // This separation makes the API cleaner since it doesn't @@ -88,6 +89,8 @@ func (t *Template) Clone() (*Template, error) { if t.common == nil { return nt, nil } + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() for k, v := range t.tmpl { if k == t.name { nt.tmpl[t.name] = nt @@ -124,6 +127,8 @@ func (t *Template) copy(c *common) *Template { // its definition. If it has been defined and already has that name, the existing // definition is replaced; otherwise a new template is created, defined, and returned. func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { + t.muTmpl.Lock() + defer t.muTmpl.Unlock() t.init() nt := t if name != t.name { @@ -142,6 +147,8 @@ func (t *Template) Templates() []*Template { return nil } // Return a slice so we don't expose the map. + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() m := make([]*Template, 0, len(t.tmpl)) for _, v := range t.tmpl { m = append(m, v) @@ -182,6 +189,8 @@ func (t *Template) Lookup(name string) *Template { if t.common == nil { return nil } + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() return t.tmpl[name] } -- cgit v1.2.3-54-g00ecf From 170a72e58bd128b421f4b3974fe2a37fd035efdf Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 9 Sep 2021 10:05:55 -0400 Subject: [release-branch.go1.16] go1.16.8 Change-Id: I1926e1506e56fd0484bec71f7b43cee62e41b5b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/348812 Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Cherry Mui Trust: Than McIntosh --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3ddf36dcfe..ead8f19bb6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -go1.16.7 \ No newline at end of file +go1.16.8 \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 552410fec2c662b8cc003c27b239d8b5bb11fcd7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 20 Aug 2021 16:55:04 -0700 Subject: [release-branch.go1.16] runtime: in adjustTimers back up as far as necessary When the adjustTimers function removed a timer it assumed it was sufficient to continue the heap traversal at that position. However, in some cases a timer will be moved to an earlier position in the heap. If that timer is timerModifiedEarlier, that can leave timerModifiedEarliest not correctly representing the earlier such timer. Fix the problem by restarting the heap traversal at the earliest changed position. For #47762 Fixes #47858 Change-Id: I152bbe62793ee40a680baf49967bcb89b1f94764 Reviewed-on: https://go-review.googlesource.com/c/go/+/343882 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Michael Knyszek (cherry picked from commit 2da3375e9b4980e368a8641f54cc53c4af4d1a12) Reviewed-on: https://go-review.googlesource.com/c/go/+/350000 --- src/runtime/time.go | 30 ++++++++++++++-------- src/time/sleep_test.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 10 deletions(-) diff --git a/src/runtime/time.go b/src/runtime/time.go index 666b242316..517a493a70 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -366,9 +366,9 @@ func deltimer(t *timer) bool { // dodeltimer removes timer i from the current P's heap. // We are locked on the P when this is called. -// It reports whether it saw no problems due to races. +// It returns the smallest changed index in pp.timers. // The caller must have locked the timers for pp. -func dodeltimer(pp *p, i int) { +func dodeltimer(pp *p, i int) int { if t := pp.timers[i]; t.pp.ptr() != pp { throw("dodeltimer: wrong P") } else { @@ -380,16 +380,18 @@ func dodeltimer(pp *p, i int) { } pp.timers[last] = nil pp.timers = pp.timers[:last] + smallestChanged := i if i != last { // Moving to i may have moved the last timer to a new parent, // so sift up to preserve the heap guarantee. - siftupTimer(pp.timers, i) + smallestChanged = siftupTimer(pp.timers, i) siftdownTimer(pp.timers, i) } if i == 0 { updateTimer0When(pp) } atomic.Xadd(&pp.numTimers, -1) + return smallestChanged } // dodeltimer0 removes timer 0 from the current P's heap. @@ -674,13 +676,14 @@ func adjusttimers(pp *p, now int64) { switch s := atomic.Load(&t.status); s { case timerDeleted: if atomic.Cas(&t.status, s, timerRemoving) { - dodeltimer(pp, i) + changed := dodeltimer(pp, i) if !atomic.Cas(&t.status, timerRemoving, timerRemoved) { badTimer() } atomic.Xadd(&pp.deletedTimers, -1) - // Look at this heap position again. - i-- + // Go back to the earliest changed heap entry. + // "- 1" because the loop will add 1. + i = changed - 1 } case timerModifiedEarlier, timerModifiedLater: if atomic.Cas(&t.status, s, timerMoving) { @@ -690,10 +693,11 @@ func adjusttimers(pp *p, now int64) { // We don't add it back yet because the // heap manipulation could cause our // loop to skip some other timer. - dodeltimer(pp, i) + changed := dodeltimer(pp, i) moved = append(moved, t) - // Look at this heap position again. - i-- + // Go back to the earliest changed heap entry. + // "- 1" because the loop will add 1. + i = changed - 1 } case timerNoStatus, timerRunning, timerRemoving, timerRemoved, timerMoving: badTimer() @@ -1043,7 +1047,10 @@ func timeSleepUntil() (int64, *p) { // "panic holding locks" message. Instead, we panic while not // holding a lock. -func siftupTimer(t []*timer, i int) { +// siftupTimer puts the timer at position i in the right place +// in the heap by moving it up toward the top of the heap. +// It returns the smallest changed index. +func siftupTimer(t []*timer, i int) int { if i >= len(t) { badTimer() } @@ -1063,8 +1070,11 @@ func siftupTimer(t []*timer, i int) { if tmp != t[i] { t[i] = tmp } + return i } +// siftdownTimer puts the timer at position i in the right place +// in the heap by moving it down toward the bottom of the heap. func siftdownTimer(t []*timer, i int) { n := len(t) if i >= n { diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go index e0172bf5e0..c48e704eb7 100644 --- a/src/time/sleep_test.go +++ b/src/time/sleep_test.go @@ -7,6 +7,7 @@ package time_test import ( "errors" "fmt" + "math/rand" "runtime" "strings" "sync" @@ -561,6 +562,72 @@ func TestTimerModifiedEarlier(t *testing.T) { } } +// Test that rapidly moving timers earlier and later doesn't cause +// some of the sleep times to be lost. +// Issue 47762 +func TestAdjustTimers(t *testing.T) { + var rnd = rand.New(rand.NewSource(Now().UnixNano())) + + timers := make([]*Timer, 100) + states := make([]int, len(timers)) + indices := rnd.Perm(len(timers)) + + for len(indices) != 0 { + var ii = rnd.Intn(len(indices)) + var i = indices[ii] + + var timer = timers[i] + var state = states[i] + states[i]++ + + switch state { + case 0: + timers[i] = NewTimer(0) + case 1: + <-timer.C // Timer is now idle. + + // Reset to various long durations, which we'll cancel. + case 2: + if timer.Reset(1 * Minute) { + panic("shouldn't be active (1)") + } + case 4: + if timer.Reset(3 * Minute) { + panic("shouldn't be active (3)") + } + case 6: + if timer.Reset(2 * Minute) { + panic("shouldn't be active (2)") + } + + // Stop and drain a long-duration timer. + case 3, 5, 7: + if !timer.Stop() { + t.Logf("timer %d state %d Stop returned false", i, state) + <-timer.C + } + + // Start a short-duration timer we expect to select without blocking. + case 8: + if timer.Reset(0) { + t.Fatal("timer.Reset returned true") + } + case 9: + now := Now() + <-timer.C + dur := Since(now) + if dur > 750*Millisecond { + t.Errorf("timer %d took %v to complete", i, dur) + } + + // Timer is done. Swap with tail and remove. + case 10: + indices[ii] = indices[len(indices)-1] + indices = indices[:len(indices)-1] + } + } +} + // Benchmark timer latency when the thread that creates the timer is busy with // other work and the timers must be serviced by other threads. // https://golang.org/issue/38860 -- cgit v1.2.3-54-g00ecf From 7d573240307331c2dc9edfbb11ebbaa6bc677e99 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 17 Sep 2021 12:27:23 -0700 Subject: [release-branch.go1.16] text/template: initialize template before locking it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For #39807 For #48436 Fixes #48443 Change-Id: I75f82fd8738dd2f11f0c69b1230e1be1abc36024 Reviewed-on: https://go-review.googlesource.com/c/go/+/350730 Trust: Ian Lance Taylor Trust: Daniel Martí Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Daniel Martí (cherry picked from commit ba1c52d7d77724de4407572bd02421c36df3d78a) Reviewed-on: https://go-review.googlesource.com/c/go/+/351116 --- src/text/template/multi_test.go | 10 ++++++++++ src/text/template/template.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/text/template/multi_test.go b/src/text/template/multi_test.go index b543ab5c47..6b81ffe7ac 100644 --- a/src/text/template/multi_test.go +++ b/src/text/template/multi_test.go @@ -452,3 +452,13 @@ func TestIssue19294(t *testing.T) { } } } + +// Issue 48436 +func TestAddToZeroTemplate(t *testing.T) { + tree, err := parse.Parse("c", cloneText3, "", "", nil, builtins()) + if err != nil { + t.Fatal(err) + } + var tmpl Template + tmpl.AddParseTree("x", tree["c"]) +} diff --git a/src/text/template/template.go b/src/text/template/template.go index fd74d45e9b..776be9cd07 100644 --- a/src/text/template/template.go +++ b/src/text/template/template.go @@ -127,9 +127,9 @@ func (t *Template) copy(c *common) *Template { // its definition. If it has been defined and already has that name, the existing // definition is replaced; otherwise a new template is created, defined, and returned. func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { + t.init() t.muTmpl.Lock() defer t.muTmpl.Unlock() - t.init() nt := t if name != t.name { nt = t.New(name) -- cgit v1.2.3-54-g00ecf From 4548fcc8dfd933c237f29bba6f90040a85922564 Mon Sep 17 00:00:00 2001 From: Michael Knyszek Date: Thu, 2 Sep 2021 16:51:59 -0400 Subject: [release-branch.go1.16] misc/wasm, cmd/link: do not let command line args overwrite global data On Wasm, wasm_exec.js puts command line arguments at the beginning of the linear memory (following the "zero page"). Currently there is no limit for this, and a very long command line can overwrite the program's data section. Prevent this by limiting the command line to 4096 bytes, and in the linker ensuring the data section starts at a high enough address (8192). (Arguably our address assignment on Wasm is a bit confusing. This is the minimum fix I can come up with.) Thanks to Ben Lubar for reporting this issue. Change by Cherry Mui . For #48797 Fixes #48799 Fixes CVE-2021-38297 Change-Id: I0f50fbb2a5b6d0d047e3c134a88988d9133e4ab3 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1205933 Reviewed-by: Roland Shoemaker Reviewed-by: Than McIntosh Reviewed-on: https://go-review.googlesource.com/c/go/+/354591 Trust: Michael Knyszek Reviewed-by: Heschi Kreinick --- misc/wasm/wasm_exec.js | 7 +++++++ src/cmd/link/internal/ld/data.go | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index 82041e6bb9..a0a264278b 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -564,6 +564,13 @@ offset += 8; }); + // The linker guarantees global data starts from at least wasmMinDataAddr. + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. + const wasmMinDataAddr = 4096 + 4096; + if (offset >= wasmMinDataAddr) { + throw new Error("command line too long"); + } + this._inst.exports.run(argc, argv); if (this.exited) { this._resolveExitPromise(); diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 52035e9630..54a1d188cd 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -2330,6 +2330,11 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64 return sect, n, va } +// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js +// to store command line args. Data sections starts from at least address 8192. +// Keep in sync with wasm_exec.js. +const wasmMinDataAddr = 4096 + 4096 + // address assigns virtual addresses to all segments and sections and // returns all segments in file order. func (ctxt *Link) address() []*sym.Segment { @@ -2339,10 +2344,14 @@ func (ctxt *Link) address() []*sym.Segment { order = append(order, &Segtext) Segtext.Rwx = 05 Segtext.Vaddr = va - for _, s := range Segtext.Sections { + for i, s := range Segtext.Sections { va = uint64(Rnd(int64(va), int64(s.Align))) s.Vaddr = va va += s.Length + + if ctxt.IsWasm() && i == 0 && va < wasmMinDataAddr { + va = wasmMinDataAddr + } } Segtext.Length = va - uint64(*FlagTextAddr) -- cgit v1.2.3-54-g00ecf From c580180744e60d6c84fc0b59d634fcff01290780 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 7 Oct 2021 14:45:12 -0400 Subject: [release-branch.go1.16] go1.16.9 Change-Id: I7328dd94a85b97ec8c3ecf4f56eca9c56a6d806e Reviewed-on: https://go-review.googlesource.com/c/go/+/354593 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Heschi Kreinick TryBot-Result: Go Bot --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ead8f19bb6..9de9e41c7a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -go1.16.8 \ No newline at end of file +go1.16.9 \ No newline at end of file -- cgit v1.2.3-54-g00ecf