aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeschi Kreinick <heschi@google.com>2021-10-07 19:02:56 -0400
committerHeschi Kreinick <heschi@google.com>2021-10-07 19:02:56 -0400
commit35d5cd0dcfb9d06064ec37da1621d24676454058 (patch)
tree5319064d4c2970a6d3be069b9c2a0e273f0f14dd
parent0d02a0d966b6d307ac33e3df3687948b74408569 (diff)
parentc580180744e60d6c84fc0b59d634fcff01290780 (diff)
downloadgo-35d5cd0dcfb9d06064ec37da1621d24676454058.tar.gz
go-35d5cd0dcfb9d06064ec37da1621d24676454058.zip
[dev.boringcrypto.go1.16] all: merge go1.16.9 into dev.boringcrypto.go1.16
Change-Id: Ic26e9802fe13c491fcc26f34b8847779ac43cfe2
-rw-r--r--misc/wasm/wasm_exec.js7
-rw-r--r--src/archive/zip/reader.go2
-rw-r--r--src/archive/zip/reader_test.go18
-rw-r--r--src/cmd/link/internal/ld/data.go11
-rw-r--r--src/go.mod2
-rw-r--r--src/go.sum4
-rw-r--r--src/go/internal/gccgoimporter/gccgoinstallation_test.go2
-rw-r--r--src/html/template/exec_test.go2
-rw-r--r--src/net/http/h2_bundle.go9
-rw-r--r--src/runtime/proc.go9
-rw-r--r--src/runtime/time.go30
-rw-r--r--src/text/template/exec.go9
-rw-r--r--src/text/template/exec_test.go38
-rw-r--r--src/text/template/multi_test.go10
-rw-r--r--src/text/template/template.go9
-rw-r--r--src/time/sleep_test.go67
-rw-r--r--src/vendor/modules.txt2
17 files changed, 206 insertions, 25 deletions
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/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)
+ }
+}
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)
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/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)
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/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/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.
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/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/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 ec26eb4c50..776be9cd07 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
@@ -125,6 +128,8 @@ func (t *Template) copy(c *common) *Template {
// 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()
nt := t
if name != t.name {
nt = t.New(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]
}
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
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