Commit d18087cb authored by Chris Broadfoot's avatar Chris Broadfoot

[release-branch.go1.8] all: merge master into release-branch.go1.8

6593d865 go/ast: fix Object's doc comment about Data
c1730ae4 runtime: force workers out before checking mark roots
d10eddcb testing: make parallel t.Run safe again
2c8b70ea crypto/x509: revert SystemCertPool implementation for Windows
fcfd9185 doc/go1.8: document Plan 9 requirements
81a61a96 runtime: for plugins, don't add duplicate itabs
f674537c README.md: update and simplify
d8711919 cmd/go: fix bug help message
48d8edb5 crypto/tls: disable CBC cipher suites with SHA-256 by default
92ecd789 cmd/compile: add ZeroWB case in writebarrier
787125ab doc: 2017 is the Year of the Gopher
5b708a6b cmd/compile: lvalues are only required for == when calling runtime fns
e83d5067 vendor/golang_org/x/crypto/poly1305: revendor to pick up fix for #18673
76f981c8 net/http: skip TestServerHijackGetsBackgroundByte on Plan 9
e395e324 net/http: skip TestServerHijackGetsBackgroundByte_big on Plan 9
6a3c6c0d net/http: add another hijack-after-background-read test
467109bf all: test adjustments for the iOS builder
b2a3b54b net/http: make sure Hijack's bufio.Reader includes pre-read background byte
593ea3b3 cmd/go, misc: rework cwd handling for iOS tests
0642b8a2 syscall: export Fsid.X__val on s390x
4601eae6 doc/gdb: mention GOTRACEBACK=crash
4c4c5fc7 misc/cgo/testplugin: test that types and itabs are unique
22689c44 reflect: keep makeFuncImpl live across makeFuncStub
9cf06ed6 cmd/link: only exclude C-only symbols on darwin
9c3630f5 compress/flate: avoid large stack growth in fillDeflate
4f0aac52 cmd/go: add comment about SIGUSR2 on iOS
333f764d cmd/go, misc: switch from breakpoint to SIGUSR2
39e31d5e doc/go1.8: update timezone database version
08da8201 misc/cgo/testshared: test that types and itabs are unique
fdde7ba2 runtime: avoid clobbering C callee-save register in cgoSigtramp
f65abf6d cmd/compile: hide testdclstack behind debug flag
641ef2a7 compress/gzip: skip TestGZIPFilesHaveZeroMTimes on non-builders
0724aa81 crypto/dsa: gofmt
ac055429 net/http: deflake TestRetryIdempotentRequestsOnError
b842c9aa doc: remove inline styles

Change-Id: I642c056732fe1e8081e9d73e086e38ea0b2568cc
parents 3de6e96e 6593d865
...@@ -5,39 +5,37 @@ reliable, and efficient software. ...@@ -5,39 +5,37 @@ reliable, and efficient software.
![Gopher image](doc/gopher/fiveyears.jpg) ![Gopher image](doc/gopher/fiveyears.jpg)
For documentation about how to install and use Go,
visit https://golang.org/ or load doc/install-source.html
in your web browser.
Our canonical Git repository is located at https://go.googlesource.com/go. Our canonical Git repository is located at https://go.googlesource.com/go.
There is a mirror of the repository at https://github.com/golang/go. There is a mirror of the repository at https://github.com/golang/go.
Go is the work of hundreds of contributors. We appreciate your help! Unless otherwise noted, the Go source files are distributed under the
BSD-style license found in the LICENSE file.
To contribute, please read the contribution guidelines: ### Download and Install
https://golang.org/doc/contribute.html
##### Note that we do not accept pull requests and that we use the issue tracker for bug reports and proposals only. Please ask questions on https://forum.golangbridge.org or https://groups.google.com/forum/#!forum/golang-nuts. #### Binary Distributions
Unless otherwise noted, the Go source files are distributed Official binary distributions are available at https://golang.org/dl/.
under the BSD-style license found in the LICENSE file.
-- After downloading a binary release, visit https://golang.org/doc/install
or load doc/install.html in your web browser for installation
instructions.
## Binary Distribution Notes #### Install From Source
If you have just untarred a binary Go distribution, you need to set If a binary distribution is not available for your combination of
the environment variable $GOROOT to the full path of the go operating system and architecture, visit
directory (the one containing this file). You can omit the https://golang.org/doc/install/source or load doc/install-source.html
variable if you unpack it into /usr/local/go, or if you rebuild in your web browser for source installation instructions.
from sources by running all.bash (see doc/install-source.html).
You should also add the Go binary directory $GOROOT/bin
to your shell's path.
For example, if you extracted the tar file into $HOME/go, you might ### Contributing
put the following in your .profile:
export GOROOT=$HOME/go Go is the work of hundreds of contributors. We appreciate your help!
export PATH=$PATH:$GOROOT/bin
To contribute, please read the contribution guidelines:
https://golang.org/doc/contribute.html
See https://golang.org/doc/install or doc/install.html for more details. Note that the Go project does not use GitHub pull requests, and that
we use the issue tracker for bug reports and proposals only. See
https://golang.org/wiki/Questions for a list of places to ask
questions about the Go language.
...@@ -698,7 +698,7 @@ These files will be periodically updated based on the commit logs. ...@@ -698,7 +698,7 @@ These files will be periodically updated based on the commit logs.
<p>Code that you contribute should use the standard copyright header:</p> <p>Code that you contribute should use the standard copyright header:</p>
<pre> <pre>
// Copyright 2016 The Go Authors. All rights reserved. // Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
</pre> </pre>
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
}--> }-->
<p><i> <p><i>
This applies to the <code>gc</code> toolchain. Gccgo has native gdb support. This applies to the standard toolchain (the <code>gc</code> Go
compiler and tools). Gccgo has native gdb support.
Besides this overview you might want to consult the Besides this overview you might want to consult the
<a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>. <a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>.
</i></p> </i></p>
...@@ -49,6 +50,14 @@ when debugging, pass the flags <code>-gcflags "-N -l"</code> to the ...@@ -49,6 +50,14 @@ when debugging, pass the flags <code>-gcflags "-N -l"</code> to the
debugged. debugged.
</p> </p>
<p>
If you want to use gdb to inspect a core dump, you can trigger a dump
on a program crash, on systems that permit it, by setting
<code>GOTRACEBACK=crash</code> in the environment (see the
<a href="/pkg/runtime/#hdr-Environment_Variables"> runtime package
documentation</a> for more info).
</p>
<h3 id="Common_Operations">Common Operations</h3> <h3 id="Common_Operations">Common Operations</h3>
<ul> <ul>
...@@ -130,7 +139,7 @@ the DWARF code. ...@@ -130,7 +139,7 @@ the DWARF code.
<p> <p>
If you're interested in what the debugging information looks like, run If you're interested in what the debugging information looks like, run
'<code>objdump -W 6.out</code>' and browse through the <code>.debug_*</code> '<code>objdump -W a.out</code>' and browse through the <code>.debug_*</code>
sections. sections.
</p> </p>
...@@ -377,7 +386,9 @@ $3 = struct hchan&lt;*testing.T&gt; ...@@ -377,7 +386,9 @@ $3 = struct hchan&lt;*testing.T&gt;
</pre> </pre>
<p> <p>
That <code>struct hchan&lt;*testing.T&gt;</code> is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it's contents. That <code>struct hchan&lt;*testing.T&gt;</code> is the
runtime-internal representation of a channel. It is currently empty,
or gdb would have pretty-printed its contents.
</p> </p>
<p> <p>
......
...@@ -93,7 +93,8 @@ On OpenBSD, Go now requires OpenBSD 5.9 or later. <!-- CL 34093 --> ...@@ -93,7 +93,8 @@ On OpenBSD, Go now requires OpenBSD 5.9 or later. <!-- CL 34093 -->
<p> <p>
The Plan 9 port's networking support is now much more complete The Plan 9 port's networking support is now much more complete
and matches the behavior of Unix and Windows with respect to deadlines and matches the behavior of Unix and Windows with respect to deadlines
and cancelation. and cancelation. For Plan 9 kernel requirements, see the
<a href="https://golang.org/wiki/Plan9">Plan 9 wiki page</a>.
</p> </p>
<p> <p>
...@@ -808,11 +809,6 @@ Optimizations and minor bug fixes are not listed. ...@@ -808,11 +809,6 @@ Optimizations and minor bug fixes are not listed.
<dl id="crypto_x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt> <dl id="crypto_x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
<dd> <dd>
<p> <!-- CL 30578 -->
<a href="/pkg/crypto/x509/#SystemCertPool"><code>SystemCertPool</code></a>
is now implemented on Windows.
</p>
<p> <!-- CL 24743 --> <p> <!-- CL 24743 -->
PSS signatures are now supported. PSS signatures are now supported.
</p> </p>
...@@ -1617,9 +1613,9 @@ crypto/x509: return error for missing SerialNumber (CL 27238) ...@@ -1617,9 +1613,9 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
June 31 and July 32. June 31 and July 32.
</p> </p>
<p> <!-- CL 33029 --> <p> <!-- CL 33029 --> <!-- CL 34816 -->
The <code>tzdata</code> database has been updated to version The <code>tzdata</code> database has been updated to version
2016i for systems that don't already have a local time zone 2016j for systems that don't already have a local time zone
database. database.
</p> </p>
......
...@@ -250,7 +250,7 @@ $ <b>cd $HOME/go/src/hello</b> ...@@ -250,7 +250,7 @@ $ <b>cd $HOME/go/src/hello</b>
$ <b>go build</b> $ <b>go build</b>
</pre> </pre>
<pre class="testWindows" style="display: none"> <pre class="testWindows">
C:\&gt; <b>cd %USERPROFILE%\go\src\hello</b> C:\&gt; <b>cd %USERPROFILE%\go\src\hello</b>
C:\Users\Gopher\go\src\hello&gt; <b>go build</b> C:\Users\Gopher\go\src\hello&gt; <b>go build</b>
</pre> </pre>
...@@ -267,7 +267,7 @@ $ <b>./hello</b> ...@@ -267,7 +267,7 @@ $ <b>./hello</b>
hello, world hello, world
</pre> </pre>
<pre class="testWindows" style="display: none"> <pre class="testWindows">
C:\Users\Gopher\go\src\hello&gt; <b>hello</b> C:\Users\Gopher\go\src\hello&gt; <b>hello</b>
hello, world hello, world
</pre> </pre>
......
// Copyright 2017 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 main
import (
"iface_i"
"log"
"plugin"
)
func main() {
a, err := plugin.Open("iface_a.so")
if err != nil {
log.Fatalf(`plugin.Open("iface_a.so"): %v`, err)
}
b, err := plugin.Open("iface_b.so")
if err != nil {
log.Fatalf(`plugin.Open("iface_b.so"): %v`, err)
}
af, err := a.Lookup("F")
if err != nil {
log.Fatalf(`a.Lookup("F") failed: %v`, err)
}
bf, err := b.Lookup("F")
if err != nil {
log.Fatalf(`b.Lookup("F") failed: %v`, err)
}
if af.(func() interface{})() != bf.(func() interface{})() {
panic("empty interfaces not equal")
}
ag, err := a.Lookup("G")
if err != nil {
log.Fatalf(`a.Lookup("G") failed: %v`, err)
}
bg, err := b.Lookup("G")
if err != nil {
log.Fatalf(`b.Lookup("G") failed: %v`, err)
}
if ag.(func() iface_i.I)() != bg.(func() iface_i.I)() {
panic("nonempty interfaces not equal")
}
}
// Copyright 2017 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 main
import "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}
// Copyright 2017 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 main
import "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}
// Copyright 2017 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 iface_i
type I interface {
M()
}
type T struct {
}
func (t *T) M() {
}
// *T implements I
// Copyright 2017 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 dynamodbstreamsevt
import "encoding/json"
var foo json.RawMessage
type Event struct{}
func (e *Event) Dummy() {}
// Copyright 2017 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.
// The bug happened like this:
// 1) The main binary adds an itab for *json.UnsupportedValueError / error
// (concrete type / interface type). This itab goes in hash bucket 0x111.
// 2) The plugin adds that same itab again. That makes a cycle in the itab
// chain rooted at hash bucket 0x111.
// 3) The main binary then asks for the itab for *dynamodbstreamsevt.Event /
// json.Unmarshaler. This itab happens to also live in bucket 0x111.
// The lookup code goes into an infinite loop searching for this itab.
// The code is carefully crafted so that the two itabs are both from the
// same bucket, and so that the second itab doesn't exist in
// the itab hashmap yet (so the entire linked list must be searched).
package main
import (
"encoding/json"
"issue18676/dynamodbstreamsevt"
"plugin"
)
func main() {
plugin.Open("plugin.so")
var x interface{} = (*dynamodbstreamsevt.Event)(nil)
if _, ok := x.(json.Unmarshaler); !ok {
println("something")
}
}
// Copyright 2017 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 main
import "C"
import "issue18676/dynamodbstreamsevt"
func F(evt *dynamodbstreamsevt.Event) {}
...@@ -15,8 +15,8 @@ goos=$(go env GOOS) ...@@ -15,8 +15,8 @@ goos=$(go env GOOS)
goarch=$(go env GOARCH) goarch=$(go env GOARCH)
function cleanup() { function cleanup() {
rm -f plugin*.so unnamed*.so rm -f plugin*.so unnamed*.so iface*.so
rm -rf host pkg sub rm -rf host pkg sub iface issue18676
} }
trap cleanup EXIT trap cleanup EXIT
...@@ -32,3 +32,15 @@ GOPATH=$(pwd) go build -buildmode=plugin unnamed2.go ...@@ -32,3 +32,15 @@ GOPATH=$(pwd) go build -buildmode=plugin unnamed2.go
GOPATH=$(pwd) go build host GOPATH=$(pwd) go build host
LD_LIBRARY_PATH=$(pwd) ./host LD_LIBRARY_PATH=$(pwd) ./host
# Test that types and itabs get properly uniqified.
GOPATH=$(pwd) go build -buildmode=plugin iface_a
GOPATH=$(pwd) go build -buildmode=plugin iface_b
GOPATH=$(pwd) go build iface
LD_LIBRARY_PATH=$(pwd) ./iface
# Test for issue 18676 - make sure we don't add the same itab twice.
# The buggy code hangs forever, so use a timeout to check for that.
GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
timeout 10s ./issue18676
...@@ -815,3 +815,14 @@ func TestImplicitInclusion(t *testing.T) { ...@@ -815,3 +815,14 @@ func TestImplicitInclusion(t *testing.T) {
goCmd(t, "install", "-linkshared", "implicitcmd") goCmd(t, "install", "-linkshared", "implicitcmd")
run(t, "running executable linked against library that contains same package as it", "./bin/implicitcmd") run(t, "running executable linked against library that contains same package as it", "./bin/implicitcmd")
} }
// Tests to make sure that the type fields of empty interfaces and itab
// fields of nonempty interfaces are unique even across modules,
// so that interface equality works correctly.
func TestInterface(t *testing.T) {
goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_a")
// Note: iface_i gets installed implicitly as a dependency of iface_a.
goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_b")
goCmd(t, "install", "-linkshared", "iface")
run(t, "running type/itab uniqueness tester", "./bin/iface")
}
// Copyright 2017 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 main
import "iface_a"
import "iface_b"
func main() {
if iface_a.F() != iface_b.F() {
panic("empty interfaces not equal")
}
if iface_a.G() != iface_b.G() {
panic("non-empty interfaces not equal")
}
}
// Copyright 2017 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 iface_a
import "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}
// Copyright 2017 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 iface_b
import "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}
// Copyright 2017 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 iface_i
type I interface {
M()
}
type T struct {
}
func (t *T) M() {
}
// *T implements I
...@@ -99,7 +99,7 @@ func main() { ...@@ -99,7 +99,7 @@ func main() {
// Approximately 1 in a 100 binaries fail to start. If it happens, // Approximately 1 in a 100 binaries fail to start. If it happens,
// try again. These failures happen for several reasons beyond // try again. These failures happen for several reasons beyond
// our control, but all of them are safe to retry as they happen // our control, but all of them are safe to retry as they happen
// before lldb encounters the initial getwd breakpoint. As we // before lldb encounters the initial SIGUSR2 stop. As we
// know the tests haven't started, we are not hiding flaky tests // know the tests haven't started, we are not hiding flaky tests
// with this retry. // with this retry.
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
...@@ -204,6 +204,11 @@ func run(bin string, args []string) (err error) { ...@@ -204,6 +204,11 @@ func run(bin string, args []string) (err error) {
var opts options var opts options
opts, args = parseArgs(args) opts, args = parseArgs(args)
// Pass the suffix for the current working directory as the
// first argument to the test. For iOS, cmd/go generates
// special handling of this argument.
args = append([]string{"cwdSuffix=" + pkgpath}, args...)
// ios-deploy invokes lldb to give us a shell session with the app. // ios-deploy invokes lldb to give us a shell session with the app.
s, err := newSession(appdir, args, opts) s, err := newSession(appdir, args, opts)
if err != nil { if err != nil {
...@@ -224,6 +229,7 @@ func run(bin string, args []string) (err error) { ...@@ -224,6 +229,7 @@ func run(bin string, args []string) (err error) {
s.do(`process handle SIGHUP --stop false --pass true --notify false`) s.do(`process handle SIGHUP --stop false --pass true --notify false`)
s.do(`process handle SIGPIPE --stop false --pass true --notify false`) s.do(`process handle SIGPIPE --stop false --pass true --notify false`)
s.do(`process handle SIGUSR1 --stop false --pass true --notify false`) s.do(`process handle SIGUSR1 --stop false --pass true --notify false`)
s.do(`process handle SIGUSR2 --stop true --pass false --notify true`) // sent by test harness
s.do(`process handle SIGCONT --stop false --pass true --notify false`) s.do(`process handle SIGCONT --stop false --pass true --notify false`)
s.do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work s.do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work
s.do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work s.do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work
...@@ -236,20 +242,9 @@ func run(bin string, args []string) (err error) { ...@@ -236,20 +242,9 @@ func run(bin string, args []string) (err error) {
return nil return nil
} }
s.do(`breakpoint set -n getwd`) // in runtime/cgo/gcc_darwin_arm.go
started = true started = true
s.doCmd("run", "stop reason = breakpoint", 20*time.Second) s.doCmd("run", "stop reason = signal SIGUSR2", 20*time.Second)
// Move the current working directory into the faux gopath.
if pkgpath != "src" {
s.do(`breakpoint delete 1`)
s.do(`expr char* $mem = (char*)malloc(512)`)
s.do(`expr $mem = (char*)getwd($mem, 512)`)
s.do(`expr $mem = (char*)strcat($mem, "/` + pkgpath + `")`)
s.do(`call (void)chdir($mem)`)
}
startTestsLen := s.out.Len() startTestsLen := s.out.Len()
fmt.Fprintln(s.in, `process continue`) fmt.Fprintln(s.in, `process continue`)
...@@ -520,13 +515,11 @@ func copyLocalData(dstbase string) (pkgpath string, err error) { ...@@ -520,13 +515,11 @@ func copyLocalData(dstbase string) (pkgpath string, err error) {
// Copy timezone file. // Copy timezone file.
// //
// Typical apps have the zoneinfo.zip in the root of their app bundle, // Apps have the zoneinfo.zip in the root of their app bundle,
// read by the time package as the working directory at initialization. // read by the time package as the working directory at initialization.
// As we move the working directory to the GOROOT pkg directory, we
// install the zoneinfo.zip file in the pkgpath.
if underGoRoot { if underGoRoot {
err := cp( err := cp(
filepath.Join(dstbase, pkgpath), dstbase,
filepath.Join(cwd, "lib", "time", "zoneinfo.zip"), filepath.Join(cwd, "lib", "time", "zoneinfo.zip"),
) )
if err != nil { if err != nil {
......
...@@ -303,7 +303,9 @@ func genhash(sym *Sym, t *Type) { ...@@ -303,7 +303,9 @@ func genhash(sym *Sym, t *Type) {
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil Curfn = nil
popdcl() popdcl()
testdclstack() if debug_dclstack != 0 {
testdclstack()
}
// Disable safemode while compiling this code: the code we // Disable safemode while compiling this code: the code we
// generate internally can refer to unsafe.Pointer. // generate internally can refer to unsafe.Pointer.
...@@ -493,7 +495,9 @@ func geneq(sym *Sym, t *Type) { ...@@ -493,7 +495,9 @@ func geneq(sym *Sym, t *Type) {
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil Curfn = nil
popdcl() popdcl()
testdclstack() if debug_dclstack != 0 {
testdclstack()
}
// Disable safemode while compiling this code: the code we // Disable safemode while compiling this code: the code we
// generate internally can refer to unsafe.Pointer. // generate internally can refer to unsafe.Pointer.
......
...@@ -217,7 +217,9 @@ func Import(in *bufio.Reader) { ...@@ -217,7 +217,9 @@ func Import(in *bufio.Reader) {
typecheckok = tcok typecheckok = tcok
resumecheckwidth() resumecheckwidth()
testdclstack() // debugging only if debug_dclstack != 0 {
testdclstack()
}
} }
func formatErrorf(format string, args ...interface{}) { func formatErrorf(format string, args ...interface{}) {
......
...@@ -30,11 +30,12 @@ var ( ...@@ -30,11 +30,12 @@ var (
) )
var ( var (
Debug_append int Debug_append int
Debug_closure int Debug_closure int
Debug_panic int debug_dclstack int
Debug_slice int Debug_panic int
Debug_wb int Debug_slice int
Debug_wb int
) )
// Debug arguments. // Debug arguments.
...@@ -48,6 +49,7 @@ var debugtab = []struct { ...@@ -48,6 +49,7 @@ var debugtab = []struct {
{"append", &Debug_append}, // print information about append compilation {"append", &Debug_append}, // print information about append compilation
{"closure", &Debug_closure}, // print information about closure compilation {"closure", &Debug_closure}, // print information about closure compilation
{"disablenil", &disable_checknil}, // disable nil checks {"disablenil", &disable_checknil}, // disable nil checks
{"dclstack", &debug_dclstack}, // run internal dclstack checks
{"gcprog", &Debug_gcprog}, // print dump of GC programs {"gcprog", &Debug_gcprog}, // print dump of GC programs
{"nil", &Debug_checknil}, // print information about nil checks {"nil", &Debug_checknil}, // print information about nil checks
{"panic", &Debug_panic}, // do not hide any compiler panic {"panic", &Debug_panic}, // do not hide any compiler panic
...@@ -325,7 +327,6 @@ func Main() { ...@@ -325,7 +327,6 @@ func Main() {
timings.Stop() timings.Stop()
timings.AddEvent(int64(lexlineno-lexlineno0), "lines") timings.AddEvent(int64(lexlineno-lexlineno0), "lines")
testdclstack()
mkpackage(localpkg.Name) // final import not used checks mkpackage(localpkg.Name) // final import not used checks
finishUniverse() finishUniverse()
......
...@@ -34,6 +34,7 @@ func parseFile(filename string) { ...@@ -34,6 +34,7 @@ func parseFile(filename string) {
} }
if nsyntaxerrors == 0 { if nsyntaxerrors == 0 {
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
testdclstack() testdclstack()
} }
} }
......
...@@ -1833,7 +1833,9 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) { ...@@ -1833,7 +1833,9 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
funcbody(fn) funcbody(fn)
Curfn = fn Curfn = fn
popdcl() popdcl()
testdclstack() if debug_dclstack != 0 {
testdclstack()
}
// wrappers where T is anonymous (struct or interface) can be duplicated. // wrappers where T is anonymous (struct or interface) can be duplicated.
if rcvr.IsStruct() || rcvr.IsInterface() || rcvr.IsPtr() && rcvr.Elem().IsStruct() { if rcvr.IsStruct() || rcvr.IsInterface() || rcvr.IsPtr() && rcvr.Elem().IsStruct() {
......
...@@ -3117,12 +3117,12 @@ func walkcompare(n *Node, init *Nodes) *Node { ...@@ -3117,12 +3117,12 @@ func walkcompare(n *Node, init *Nodes) *Node {
cmpr = cmpr.Left cmpr = cmpr.Left
} }
if !islvalue(cmpl) || !islvalue(cmpr) {
Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
}
// Chose not to inline. Call equality function directly. // Chose not to inline. Call equality function directly.
if !inline { if !inline {
if !islvalue(cmpl) || !islvalue(cmpr) {
Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
}
// eq algs take pointers // eq algs take pointers
pl := temp(ptrto(t)) pl := temp(ptrto(t))
al := nod(OAS, pl, nod(OADDR, cmpl, nil)) al := nod(OAS, pl, nod(OADDR, cmpl, nil))
......
...@@ -35,7 +35,7 @@ func writebarrier(f *Func) { ...@@ -35,7 +35,7 @@ func writebarrier(f *Func) {
valueLoop: valueLoop:
for i, v := range b.Values { for i, v := range b.Values {
switch v.Op { switch v.Op {
case OpStoreWB, OpMoveWB, OpMoveWBVolatile: case OpStoreWB, OpMoveWB, OpMoveWBVolatile, OpZeroWB:
if IsStackAddr(v.Args[0]) { if IsStackAddr(v.Args[0]) {
switch v.Op { switch v.Op {
case OpStoreWB: case OpStoreWB:
......
...@@ -20,11 +20,10 @@ import ( ...@@ -20,11 +20,10 @@ import (
var cmdBug = &Command{ var cmdBug = &Command{
Run: runBug, Run: runBug,
UsageLine: "bug", UsageLine: "bug",
Short: "print information for bug reports", Short: "start a bug report",
Long: ` Long: `
Bug prints information that helps file effective bug reports. Bug opens the default browser and starts a new bug report.
The report includes useful system information.
Bugs may be reported at https://golang.org/issue/new.
`, `,
} }
......
...@@ -894,9 +894,13 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, ...@@ -894,9 +894,13 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
if buildContext.GOOS == "darwin" { if buildContext.GOOS == "darwin" {
if buildContext.GOARCH == "arm" || buildContext.GOARCH == "arm64" { if buildContext.GOARCH == "arm" || buildContext.GOARCH == "arm64" {
t.NeedCgo = true t.IsIOS = true
t.NeedOS = true
} }
} }
if t.TestMain == nil {
t.NeedOS = true
}
for _, cp := range pmain.imports { for _, cp := range pmain.imports {
if len(cp.coverVars) > 0 { if len(cp.coverVars) > 0 {
...@@ -1343,7 +1347,8 @@ type testFuncs struct { ...@@ -1343,7 +1347,8 @@ type testFuncs struct {
NeedTest bool NeedTest bool
ImportXtest bool ImportXtest bool
NeedXtest bool NeedXtest bool
NeedCgo bool NeedOS bool
IsIOS bool
Cover []coverInfo Cover []coverInfo
} }
...@@ -1444,7 +1449,7 @@ var testmainTmpl = template.Must(template.New("main").Parse(` ...@@ -1444,7 +1449,7 @@ var testmainTmpl = template.Must(template.New("main").Parse(`
package main package main
import ( import (
{{if not .TestMain}} {{if .NeedOS}}
"os" "os"
{{end}} {{end}}
"testing" "testing"
...@@ -1460,8 +1465,10 @@ import ( ...@@ -1460,8 +1465,10 @@ import (
_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
{{end}} {{end}}
{{if .NeedCgo}} {{if .IsIOS}}
"os/signal"
_ "runtime/cgo" _ "runtime/cgo"
"syscall"
{{end}} {{end}}
) )
...@@ -1523,6 +1530,32 @@ func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts ...@@ -1523,6 +1530,32 @@ func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts
{{end}} {{end}}
func main() { func main() {
{{if .IsIOS}}
// Send a SIGUSR2, which will be intercepted by LLDB to
// tell the test harness that installation was successful.
// See misc/ios/go_darwin_arm_exec.go.
signal.Notify(make(chan os.Signal), syscall.SIGUSR2)
syscall.Kill(0, syscall.SIGUSR2)
signal.Reset(syscall.SIGUSR2)
// The first argument supplied to an iOS test is an offset
// suffix for the current working directory.
// Process it here, and remove it from os.Args.
const hdr = "cwdSuffix="
if len(os.Args) < 2 || len(os.Args[1]) <= len(hdr) || os.Args[1][:len(hdr)] != hdr {
panic("iOS test not passed a working directory suffix")
}
suffix := os.Args[1][len(hdr):]
dir, err := os.Getwd()
if err != nil {
panic(err)
}
if err := os.Chdir(dir + "/" + suffix); err != nil {
panic(err)
}
os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
{{end}}
{{if .CoverEnabled}} {{if .CoverEnabled}}
testing.RegisterCover(testing.Cover{ testing.RegisterCover(testing.Cover{
Mode: {{printf "%q" .CoverMode}}, Mode: {{printf "%q" .CoverMode}},
......
...@@ -168,7 +168,7 @@ func container(s *Symbol) int { ...@@ -168,7 +168,7 @@ func container(s *Symbol) int {
if s == nil { if s == nil {
return 0 return 0
} }
if Buildmode == BuildmodePlugin && onlycsymbol(s) { if Buildmode == BuildmodePlugin && Headtype == obj.Hdarwin && onlycsymbol(s) {
return 1 return 1
} }
// We want to generate func table entries only for the "lowest level" symbols, // We want to generate func table entries only for the "lowest level" symbols,
......
...@@ -204,12 +204,6 @@ func TestMTF(t *testing.T) { ...@@ -204,12 +204,6 @@ func TestMTF(t *testing.T) {
} }
} }
var (
digits = mustLoadFile("testdata/e.txt.bz2")
twain = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.bz2")
random = mustLoadFile("testdata/random.data.bz2")
)
func benchmarkDecode(b *testing.B, compressed []byte) { func benchmarkDecode(b *testing.B, compressed []byte) {
// Determine the uncompressed size of testfile. // Determine the uncompressed size of testfile.
uncompressedSize, err := io.Copy(ioutil.Discard, NewReader(bytes.NewReader(compressed))) uncompressedSize, err := io.Copy(ioutil.Discard, NewReader(bytes.NewReader(compressed)))
...@@ -227,6 +221,18 @@ func benchmarkDecode(b *testing.B, compressed []byte) { ...@@ -227,6 +221,18 @@ func benchmarkDecode(b *testing.B, compressed []byte) {
} }
} }
func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) } func BenchmarkDecodeDigits(b *testing.B) {
func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) } digits := mustLoadFile("testdata/e.txt.bz2")
func BenchmarkDecodeRand(b *testing.B) { benchmarkDecode(b, random) } b.ResetTimer()
benchmarkDecode(b, digits)
}
func BenchmarkDecodeTwain(b *testing.B) {
twain := mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.bz2")
b.ResetTimer()
benchmarkDecode(b, twain)
}
func BenchmarkDecodeRand(b *testing.B) {
random := mustLoadFile("testdata/random.data.bz2")
b.ResetTimer()
benchmarkDecode(b, random)
}
...@@ -136,14 +136,17 @@ func (d *compressor) fillDeflate(b []byte) int { ...@@ -136,14 +136,17 @@ func (d *compressor) fillDeflate(b []byte) int {
delta := d.hashOffset - 1 delta := d.hashOffset - 1
d.hashOffset -= delta d.hashOffset -= delta
d.chainHead -= delta d.chainHead -= delta
for i, v := range d.hashPrev {
// Iterate over slices instead of arrays to avoid copying
// the entire table onto the stack (Issue #18625).
for i, v := range d.hashPrev[:] {
if int(v) > delta { if int(v) > delta {
d.hashPrev[i] = uint32(int(v) - delta) d.hashPrev[i] = uint32(int(v) - delta)
} else { } else {
d.hashPrev[i] = 0 d.hashPrev[i] = 0
} }
} }
for i, v := range d.hashHead { for i, v := range d.hashHead[:] {
if int(v) > delta { if int(v) > delta {
d.hashHead[i] = uint32(int(v) - delta) d.hashHead[i] = uint32(int(v) - delta)
} else { } else {
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"reflect" "reflect"
"runtime/debug"
"sync" "sync"
"testing" "testing"
) )
...@@ -864,3 +865,33 @@ func TestBestSpeedMaxMatchOffset(t *testing.T) { ...@@ -864,3 +865,33 @@ func TestBestSpeedMaxMatchOffset(t *testing.T) {
} }
} }
} }
func TestMaxStackSize(t *testing.T) {
// This test must not run in parallel with other tests as debug.SetMaxStack
// affects all goroutines.
n := debug.SetMaxStack(1 << 16)
defer debug.SetMaxStack(n)
var wg sync.WaitGroup
defer wg.Wait()
b := make([]byte, 1<<20)
for level := HuffmanOnly; level <= BestCompression; level++ {
// Run in separate goroutine to increase probability of stack regrowth.
wg.Add(1)
go func(level int) {
defer wg.Done()
zw, err := NewWriter(ioutil.Discard, level)
if err != nil {
t.Errorf("level %d, NewWriter() = %v, want nil", level, err)
}
if n, err := zw.Write(b); n != len(b) || err != nil {
t.Errorf("level %d, Write() = (%d, %v), want (%d, nil)", level, n, err, len(b))
}
if err := zw.Close(); err != nil {
t.Errorf("level %d, Close() = %v, want nil", level, err)
}
zw.Reset(ioutil.Discard)
}(level)
}
}
...@@ -60,7 +60,7 @@ func newDeflateFast() *deflateFast { ...@@ -60,7 +60,7 @@ func newDeflateFast() *deflateFast {
func (e *deflateFast) encode(dst []token, src []byte) []token { func (e *deflateFast) encode(dst []token, src []byte) []token {
// Ensure that e.cur doesn't wrap. // Ensure that e.cur doesn't wrap.
if e.cur > 1<<30 { if e.cur > 1<<30 {
*e = deflateFast{cur: maxStoreBlockSize, prev: e.prev[:0]} e.resetAll()
} }
// This check isn't in the Snappy implementation, but there, the caller // This check isn't in the Snappy implementation, but there, the caller
...@@ -265,6 +265,21 @@ func (e *deflateFast) reset() { ...@@ -265,6 +265,21 @@ func (e *deflateFast) reset() {
// Protect against e.cur wraparound. // Protect against e.cur wraparound.
if e.cur > 1<<30 { if e.cur > 1<<30 {
*e = deflateFast{cur: maxStoreBlockSize, prev: e.prev[:0]} e.resetAll()
}
}
// resetAll resets the deflateFast struct and is only called in rare
// situations to prevent integer overflow. It manually resets each field
// to avoid causing large stack growth.
//
// See https://golang.org/issue/18636.
func (e *deflateFast) resetAll() {
// This is equivalent to:
// *e = deflateFast{cur: maxStoreBlockSize, prev: e.prev[:0]}
e.cur = maxStoreBlockSize
e.prev = e.prev[:0]
for i := range e.table {
e.table[i] = tableEntry{}
} }
} }
...@@ -9,11 +9,17 @@ import ( ...@@ -9,11 +9,17 @@ import (
"testing" "testing"
) )
// Per golang.org/issue/14937, check that every .gz file // TestGZIPFilesHaveZeroMTimes checks that every .gz file in the tree
// in the tree has a zero mtime. // has a zero MTIME. This is a requirement for the Debian maintainers
// to be able to have deterministic packages.
//
// See https://golang.org/issue/14937.
func TestGZIPFilesHaveZeroMTimes(t *testing.T) { func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
if testing.Short() && testenv.Builder() == "" { // To avoid spurious false positives due to untracked GZIP files that
t.Skip("skipping in short mode") // may be in the user's GOROOT (Issue 18604), we only run this test on
// the builders, which should have a clean checkout of the tree.
if testenv.Builder() == "" {
t.Skip("skipping test on non-builder")
} }
goroot, err := filepath.EvalSymlinks(runtime.GOROOT()) goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
if err != nil { if err != nil {
......
...@@ -95,7 +95,7 @@ func TestSignAndVerify(t *testing.T) { ...@@ -95,7 +95,7 @@ func TestSignAndVerify(t *testing.T) {
func TestSigningWithDegenerateKeys(t *testing.T) { func TestSigningWithDegenerateKeys(t *testing.T) {
// Signing with degenerate private keys should not cause an infinite // Signing with degenerate private keys should not cause an infinite
// loop. // loop.
badKeys := []struct{ badKeys := []struct {
p, q, g, y, x string p, q, g, y, x string
}{ }{
{"00", "01", "00", "00", "00"}, {"00", "01", "00", "00", "00"},
...@@ -105,7 +105,7 @@ func TestSigningWithDegenerateKeys(t *testing.T) { ...@@ -105,7 +105,7 @@ func TestSigningWithDegenerateKeys(t *testing.T) {
for i, test := range badKeys { for i, test := range badKeys {
priv := PrivateKey{ priv := PrivateKey{
PublicKey: PublicKey{ PublicKey: PublicKey{
Parameters: Parameters { Parameters: Parameters{
P: fromHex(test.p), P: fromHex(test.p),
Q: fromHex(test.q), Q: fromHex(test.q),
G: fromHex(test.g), G: fromHex(test.g),
......
...@@ -84,15 +84,15 @@ var cipherSuites = []*cipherSuite{ ...@@ -84,15 +84,15 @@ var cipherSuites = []*cipherSuite{
{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM}, {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil}, {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
package tls package tls
// BUG(agl): The crypto/tls package only implements some countermeasures // BUG(agl): The crypto/tls package only implements some countermeasures
// against Lucky13 attacks on CBC-mode encryption. See // against Lucky13 attacks on CBC-mode encryption, and only on SHA1
// http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and // variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. // https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
import ( import (
......
...@@ -4,7 +4,11 @@ ...@@ -4,7 +4,11 @@
package x509 package x509
import "encoding/pem" import (
"encoding/pem"
"errors"
"runtime"
)
// CertPool is a set of certificates. // CertPool is a set of certificates.
type CertPool struct { type CertPool struct {
...@@ -26,6 +30,11 @@ func NewCertPool() *CertPool { ...@@ -26,6 +30,11 @@ func NewCertPool() *CertPool {
// Any mutations to the returned pool are not written to disk and do // Any mutations to the returned pool are not written to disk and do
// not affect any other pool. // not affect any other pool.
func SystemCertPool() (*CertPool, error) { func SystemCertPool() (*CertPool, error) {
if runtime.GOOS == "windows" {
// Issue 16736, 18609:
return nil, errors.New("crypto/x509: system root pool is not available on Windows")
}
return loadSystemRoots() return loadSystemRoots()
} }
......
...@@ -226,6 +226,11 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate ...@@ -226,6 +226,11 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
} }
func loadSystemRoots() (*CertPool, error) { func loadSystemRoots() (*CertPool, error) {
// TODO: restore this functionality on Windows. We tried to do
// it in Go 1.8 but had to revert it. See Issue 18609.
// Returning (nil, nil) was the old behavior, prior to CL 30578.
return nil, nil
const CRYPT_E_NOT_FOUND = 0x80092004 const CRYPT_E_NOT_FOUND = 0x80092004
store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT")) store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT"))
......
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"net" "net"
"os/exec" "os/exec"
"reflect" "reflect"
"runtime"
"strings" "strings"
"testing" "testing"
"time" "time"
...@@ -1477,6 +1478,9 @@ func TestMultipleRDN(t *testing.T) { ...@@ -1477,6 +1478,9 @@ func TestMultipleRDN(t *testing.T) {
} }
func TestSystemCertPool(t *testing.T) { func TestSystemCertPool(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("not implemented on Windows; Issue 16736, 18609")
}
_, err := SystemCertPool() _, err := SystemCertPool()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
......
...@@ -70,10 +70,8 @@ func (s *Scope) String() string { ...@@ -70,10 +70,8 @@ func (s *Scope) String() string {
// The Data fields contains object-specific data: // The Data fields contains object-specific data:
// //
// Kind Data type Data value // Kind Data type Data value
// Pkg *types.Package package scope // Pkg *Scope package scope
// Con int iota for the respective declaration // Con int iota for the respective declaration
// Con != nil constant value
// Typ *Scope (used as method scope during type checking - transient)
// //
type Object struct { type Object struct {
Kind ObjKind Kind ObjKind
......
...@@ -25,7 +25,7 @@ var files = flag.String("files", "", "consider only Go test files matching this ...@@ -25,7 +25,7 @@ var files = flag.String("files", "", "consider only Go test files matching this
const dataDir = "testdata" const dataDir = "testdata"
var templateTxt = readTemplate("template.txt") var templateTxt *template.Template
func readTemplate(filename string) *template.Template { func readTemplate(filename string) *template.Template {
t := template.New(filename) t := template.New(filename)
...@@ -96,6 +96,9 @@ func test(t *testing.T, mode Mode) { ...@@ -96,6 +96,9 @@ func test(t *testing.T, mode Mode) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if templateTxt == nil {
templateTxt = readTemplate("template.txt")
}
// test packages // test packages
for _, pkg := range pkgs { for _, pkg := range pkgs {
......
...@@ -10,17 +10,12 @@ import ( ...@@ -10,17 +10,12 @@ import (
"testing" "testing"
) )
var src = readFile("parser.go") func BenchmarkParse(b *testing.B) {
src, err := ioutil.ReadFile("parser.go")
func readFile(filename string) []byte {
data, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
panic(err) b.Fatal(err)
} }
return data b.ResetTimer()
}
func BenchmarkParse(b *testing.B) {
b.SetBytes(int64(len(src))) b.SetBytes(int64(len(src)))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if _, err := ParseFile(token.NewFileSet(), "", src, ParseComments); err != nil { if _, err := ParseFile(token.NewFileSet(), "", src, ParseComments); err != nil {
......
...@@ -5173,3 +5173,142 @@ func TestServerDuplicateBackgroundRead(t *testing.T) { ...@@ -5173,3 +5173,142 @@ func TestServerDuplicateBackgroundRead(t *testing.T) {
} }
wg.Wait() wg.Wait()
} }
// Test that the bufio.Reader returned by Hijack includes any buffered
// byte (from the Server's backgroundRead) in its buffer. We want the
// Handler code to be able to tell that a byte is available via
// bufio.Reader.Buffered(), without resorting to Reading it
// (potentially blocking) to get at it.
func TestServerHijackGetsBackgroundByte(t *testing.T) {
if runtime.GOOS == "plan9" {
t.Skip("skipping test; see https://golang.org/issue/18657")
}
setParallel(t)
defer afterTest(t)
done := make(chan struct{})
inHandler := make(chan bool, 1)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
defer close(done)
// Tell the client to send more data after the GET request.
inHandler <- true
// Wait until the HTTP server sees the extra data
// after the GET request. The HTTP server fires the
// close notifier here, assuming it's a pipelined
// request, as documented.
select {
case <-w.(CloseNotifier).CloseNotify():
case <-time.After(5 * time.Second):
t.Error("timeout")
return
}
conn, buf, err := w.(Hijacker).Hijack()
if err != nil {
t.Error(err)
return
}
defer conn.Close()
n := buf.Reader.Buffered()
if n != 1 {
t.Errorf("buffered data = %d; want 1", n)
}
peek, err := buf.Reader.Peek(3)
if string(peek) != "foo" || err != nil {
t.Errorf("Peek = %q, %v; want foo, nil", peek, err)
}
}))
defer ts.Close()
cn, err := net.Dial("tcp", ts.Listener.Addr().String())
if err != nil {
t.Fatal(err)
}
defer cn.Close()
if _, err := cn.Write([]byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")); err != nil {
t.Fatal(err)
}
<-inHandler
if _, err := cn.Write([]byte("foo")); err != nil {
t.Fatal(err)
}
if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
t.Fatal(err)
}
select {
case <-done:
case <-time.After(2 * time.Second):
t.Error("timeout")
}
}
// Like TestServerHijackGetsBackgroundByte above but sending a
// immediate 1MB of data to the server to fill up the server's 4KB
// buffer.
func TestServerHijackGetsBackgroundByte_big(t *testing.T) {
if runtime.GOOS == "plan9" {
t.Skip("skipping test; see https://golang.org/issue/18657")
}
setParallel(t)
defer afterTest(t)
done := make(chan struct{})
const size = 8 << 10
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
defer close(done)
// Wait until the HTTP server sees the extra data
// after the GET request. The HTTP server fires the
// close notifier here, assuming it's a pipelined
// request, as documented.
select {
case <-w.(CloseNotifier).CloseNotify():
case <-time.After(5 * time.Second):
t.Error("timeout")
return
}
conn, buf, err := w.(Hijacker).Hijack()
if err != nil {
t.Error(err)
return
}
defer conn.Close()
slurp, err := ioutil.ReadAll(buf.Reader)
if err != nil {
t.Error("Copy: %v", err)
}
allX := true
for _, v := range slurp {
if v != 'x' {
allX = false
}
}
if len(slurp) != size {
t.Errorf("read %d; want %d", len(slurp), size)
} else if !allX {
t.Errorf("read %q; want %d 'x'", slurp, size)
}
}))
defer ts.Close()
cn, err := net.Dial("tcp", ts.Listener.Addr().String())
if err != nil {
t.Fatal(err)
}
defer cn.Close()
if _, err := fmt.Fprintf(cn, "GET / HTTP/1.1\r\nHost: e.com\r\n\r\n%s",
strings.Repeat("x", size)); err != nil {
t.Fatal(err)
}
if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
t.Fatal(err)
}
select {
case <-done:
case <-time.After(2 * time.Second):
t.Error("timeout")
}
}
...@@ -164,7 +164,7 @@ type Flusher interface { ...@@ -164,7 +164,7 @@ type Flusher interface {
// should always test for this ability at runtime. // should always test for this ability at runtime.
type Hijacker interface { type Hijacker interface {
// Hijack lets the caller take over the connection. // Hijack lets the caller take over the connection.
// After a call to Hijack(), the HTTP server library // After a call to Hijack the HTTP server library
// will not do anything else with the connection. // will not do anything else with the connection.
// //
// It becomes the caller's responsibility to manage // It becomes the caller's responsibility to manage
...@@ -174,6 +174,9 @@ type Hijacker interface { ...@@ -174,6 +174,9 @@ type Hijacker interface {
// already set, depending on the configuration of the // already set, depending on the configuration of the
// Server. It is the caller's responsibility to set // Server. It is the caller's responsibility to set
// or clear those deadlines as needed. // or clear those deadlines as needed.
//
// The returned bufio.Reader may contain unprocessed buffered
// data from the client.
Hijack() (net.Conn, *bufio.ReadWriter, error) Hijack() (net.Conn, *bufio.ReadWriter, error)
} }
...@@ -293,6 +296,11 @@ func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) { ...@@ -293,6 +296,11 @@ func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
rwc.SetDeadline(time.Time{}) rwc.SetDeadline(time.Time{})
buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc)) buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc))
if c.r.hasByte {
if _, err := c.bufr.Peek(c.bufr.Buffered() + 1); err != nil {
return nil, nil, fmt.Errorf("unexpected Peek failure reading buffered byte: %v", err)
}
}
c.setState(rwc, StateHijacked) c.setState(rwc, StateHijacked)
return return
} }
......
...@@ -36,6 +36,7 @@ import ( ...@@ -36,6 +36,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"testing" "testing"
"time" "time"
) )
...@@ -2545,6 +2546,13 @@ type closerFunc func() error ...@@ -2545,6 +2546,13 @@ type closerFunc func() error
func (f closerFunc) Close() error { return f() } func (f closerFunc) Close() error { return f() }
type writerFuncConn struct {
net.Conn
write func(p []byte) (n int, err error)
}
func (c writerFuncConn) Write(p []byte) (n int, err error) { return c.write(p) }
// Issue 4677. If we try to reuse a connection that the server is in the // Issue 4677. If we try to reuse a connection that the server is in the
// process of closing, we may end up successfully writing out our request (or a // process of closing, we may end up successfully writing out our request (or a
// portion of our request) only to find a connection error when we try to read // portion of our request) only to find a connection error when we try to read
...@@ -2557,66 +2565,78 @@ func (f closerFunc) Close() error { return f() } ...@@ -2557,66 +2565,78 @@ func (f closerFunc) Close() error { return f() }
func TestRetryIdempotentRequestsOnError(t *testing.T) { func TestRetryIdempotentRequestsOnError(t *testing.T) {
defer afterTest(t) defer afterTest(t)
var (
mu sync.Mutex
logbuf bytes.Buffer
)
logf := func(format string, args ...interface{}) {
mu.Lock()
defer mu.Unlock()
fmt.Fprintf(&logbuf, format, args...)
logbuf.WriteByte('\n')
}
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
logf("Handler")
w.Header().Set("X-Status", "ok")
})) }))
defer ts.Close() defer ts.Close()
tr := &Transport{} var writeNumAtomic int32
tr := &Transport{
Dial: func(network, addr string) (net.Conn, error) {
logf("Dial")
c, err := net.Dial(network, ts.Listener.Addr().String())
if err != nil {
logf("Dial error: %v", err)
return nil, err
}
return &writerFuncConn{
Conn: c,
write: func(p []byte) (n int, err error) {
if atomic.AddInt32(&writeNumAtomic, 1) == 2 {
logf("intentional write failure")
return 0, errors.New("second write fails")
}
logf("Write(%q)", p)
return c.Write(p)
},
}, nil
},
}
defer tr.CloseIdleConnections()
c := &Client{Transport: tr} c := &Client{Transport: tr}
const N = 2
retryc := make(chan struct{}, N)
SetRoundTripRetried(func() { SetRoundTripRetried(func() {
retryc <- struct{}{} logf("Retried.")
}) })
defer SetRoundTripRetried(nil) defer SetRoundTripRetried(nil)
for n := 0; n < 100; n++ { for i := 0; i < 3; i++ {
// open 2 conns res, err := c.Get("http://fake.golang/")
errc := make(chan error, N) if err != nil {
for i := 0; i < N; i++ { t.Fatalf("i=%d: Get = %v", i, err)
// start goroutines, send on errc
go func() {
res, err := c.Get(ts.URL)
if err == nil {
res.Body.Close()
}
errc <- err
}()
}
for i := 0; i < N; i++ {
if err := <-errc; err != nil {
t.Fatal(err)
}
}
ts.CloseClientConnections()
for i := 0; i < N; i++ {
go func() {
res, err := c.Get(ts.URL)
if err == nil {
res.Body.Close()
}
errc <- err
}()
} }
res.Body.Close()
}
for i := 0; i < N; i++ { mu.Lock()
if err := <-errc; err != nil { got := logbuf.String()
t.Fatal(err) mu.Unlock()
} const want = `Dial
} Write("GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n")
for i := 0; i < N; i++ { Handler
select { intentional write failure
case <-retryc: Retried.
// we triggered a retry, test was successful Dial
t.Logf("finished after %d runs\n", n) Write("GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n")
return Handler
default: Write("GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n")
} Handler
} `
if got != want {
t.Errorf("Log of events differs. Got:\n%s\nWant:\n%s", got, want)
} }
t.Fatal("did not trigger any retries")
} }
// Issue 6981 // Issue 6981
......
...@@ -54,12 +54,15 @@ var sysdir = func() *sysDir { ...@@ -54,12 +54,15 @@ var sysdir = func() *sysDir {
case "darwin": case "darwin":
switch runtime.GOARCH { switch runtime.GOARCH {
case "arm", "arm64": case "arm", "arm64":
/// At this point the test harness has not had a chance
// to move us into the ./src/os directory, so the
// current working directory is the root of the app.
wd, err := syscall.Getwd() wd, err := syscall.Getwd()
if err != nil { if err != nil {
wd = err.Error() wd = err.Error()
} }
return &sysDir{ return &sysDir{
filepath.Join(wd, "..", ".."), wd,
[]string{ []string{
"ResourceRules.plist", "ResourceRules.plist",
"Info.plist", "Info.plist",
......
...@@ -26,6 +26,8 @@ import ( ...@@ -26,6 +26,8 @@ import (
"unsafe" "unsafe"
) )
var sink interface{}
func TestBool(t *testing.T) { func TestBool(t *testing.T) {
v := ValueOf(true) v := ValueOf(true)
if v.Bool() != true { if v.Bool() != true {
...@@ -5331,6 +5333,72 @@ func TestCallGC(t *testing.T) { ...@@ -5331,6 +5333,72 @@ func TestCallGC(t *testing.T) {
f2("four", "five5", "six666", "seven77", "eight888") f2("four", "five5", "six666", "seven77", "eight888")
} }
// Issue 18635 (function version).
func TestKeepFuncLive(t *testing.T) {
// Test that we keep makeFuncImpl live as long as it is
// referenced on the stack.
typ := TypeOf(func(i int) {})
var f, g func(in []Value) []Value
f = func(in []Value) []Value {
clobber()
i := int(in[0].Int())
if i > 0 {
// We can't use Value.Call here because
// runtime.call* will keep the makeFuncImpl
// alive. However, by converting it to an
// interface value and calling that,
// reflect.callReflect is the only thing that
// can keep the makeFuncImpl live.
//
// Alternate between f and g so that if we do
// reuse the memory prematurely it's more
// likely to get obviously corrupted.
MakeFunc(typ, g).Interface().(func(i int))(i - 1)
}
return nil
}
g = func(in []Value) []Value {
clobber()
i := int(in[0].Int())
MakeFunc(typ, f).Interface().(func(i int))(i)
return nil
}
MakeFunc(typ, f).Call([]Value{ValueOf(10)})
}
// Issue 18635 (method version).
type KeepMethodLive struct{}
func (k KeepMethodLive) Method1(i int) {
clobber()
if i > 0 {
ValueOf(k).MethodByName("Method2").Interface().(func(i int))(i - 1)
}
}
func (k KeepMethodLive) Method2(i int) {
clobber()
ValueOf(k).MethodByName("Method1").Interface().(func(i int))(i)
}
func TestKeepMethodLive(t *testing.T) {
// Test that we keep methodValue live as long as it is
// referenced on the stack.
KeepMethodLive{}.Method1(10)
}
// clobber tries to clobber unreachable memory.
func clobber() {
runtime.GC()
for i := 1; i < 32; i++ {
for j := 0; j < 10; j++ {
obj := make([]*byte, i)
sink = obj
}
}
runtime.GC()
}
type funcLayoutTest struct { type funcLayoutTest struct {
rcvr, t Type rcvr, t Type
size, argsize, retOffset uintptr size, argsize, retOffset uintptr
......
...@@ -538,6 +538,11 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) { ...@@ -538,6 +538,11 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
off += typ.size off += typ.size
} }
} }
// runtime.getArgInfo expects to be able to find ctxt on the
// stack when it finds our caller, makeFuncStub. Make sure it
// doesn't get garbage collected.
runtime.KeepAlive(ctxt)
} }
// methodReceiver returns information about the receiver // methodReceiver returns information about the receiver
...@@ -650,6 +655,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) { ...@@ -650,6 +655,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
// though it's a heap object. // though it's a heap object.
memclrNoHeapPointers(args, frametype.size) memclrNoHeapPointers(args, frametype.size)
framePool.Put(args) framePool.Put(args)
// See the comment in callReflect.
runtime.KeepAlive(ctxt)
} }
// funcName returns the name of f, for use in error messages. // funcName returns the name of f, for use in error messages.
......
...@@ -1129,8 +1129,6 @@ top: ...@@ -1129,8 +1129,6 @@ top:
// sitting in the per-P work caches. // sitting in the per-P work caches.
// Flush and disable work caches. // Flush and disable work caches.
gcMarkRootCheck()
// Disallow caching workbufs and indicate that we're in mark 2. // Disallow caching workbufs and indicate that we're in mark 2.
gcBlackenPromptly = true gcBlackenPromptly = true
...@@ -1153,6 +1151,16 @@ top: ...@@ -1153,6 +1151,16 @@ top:
}) })
}) })
// Check that roots are marked. We should be able to
// do this before the forEachP, but based on issue
// #16083 there may be a (harmless) race where we can
// enter mark 2 while some workers are still scanning
// stacks. The forEachP ensures these scans are done.
//
// TODO(austin): Figure out the race and fix this
// properly.
gcMarkRootCheck()
// Now we can start up mark 2 workers. // Now we can start up mark 2 workers.
atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 0xffffffff) atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 0xffffffff)
atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, 0xffffffff) atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, 0xffffffff)
......
...@@ -56,7 +56,9 @@ func plugin_lastmoduleinit() (path string, syms map[string]interface{}, mismatch ...@@ -56,7 +56,9 @@ func plugin_lastmoduleinit() (path string, syms map[string]interface{}, mismatch
lock(&ifaceLock) lock(&ifaceLock)
for _, i := range md.itablinks { for _, i := range md.itablinks {
additab(i, true, false) if i.inhash == 0 {
additab(i, true, false)
}
} }
unlock(&ifaceLock) unlock(&ifaceLock)
......
...@@ -330,9 +330,9 @@ sigtrampnog: ...@@ -330,9 +330,9 @@ sigtrampnog:
// Lock sigprofCallersUse. // Lock sigprofCallersUse.
MOVL $0, AX MOVL $0, AX
MOVL $1, CX MOVL $1, CX
MOVQ $runtime·sigprofCallersUse(SB), BX MOVQ $runtime·sigprofCallersUse(SB), R11
LOCK LOCK
CMPXCHGL CX, 0(BX) CMPXCHGL CX, 0(R11)
JNZ sigtramp // Skip stack trace if already locked. JNZ sigtramp // Skip stack trace if already locked.
// Jump to the traceback function in runtime/cgo. // Jump to the traceback function in runtime/cgo.
......
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
"log" "log"
"os" "os"
"regexp" "regexp"
"strings"
) )
func main() { func main() {
...@@ -38,10 +39,16 @@ func main() { ...@@ -38,10 +39,16 @@ func main() {
re = regexp.MustCompile("Pad_cgo[A-Za-z0-9_]*") re = regexp.MustCompile("Pad_cgo[A-Za-z0-9_]*")
s = re.ReplaceAllString(s, "_") s = re.ReplaceAllString(s, "_")
// We want to keep X__val in Fsid. Hide it and restore it later.
s = strings.Replace(s, "X__val", "MKPOSTFSIDVAL", 1)
// Replace other unwanted fields with blank identifiers. // Replace other unwanted fields with blank identifiers.
re = regexp.MustCompile("X_[A-Za-z0-9_]*") re = regexp.MustCompile("X_[A-Za-z0-9_]*")
s = re.ReplaceAllString(s, "_") s = re.ReplaceAllString(s, "_")
// Restore X__val in Fsid.
s = strings.Replace(s, "MKPOSTFSIDVAL", "X__val", 1)
// Force the type of RawSockaddr.Data to [14]int8 to match // Force the type of RawSockaddr.Data to [14]int8 to match
// the existing gccgo API. // the existing gccgo API.
re = regexp.MustCompile("(Data\\s+\\[14\\])uint8") re = regexp.MustCompile("(Data\\s+\\[14\\])uint8")
......
...@@ -140,7 +140,7 @@ type Dirent struct { ...@@ -140,7 +140,7 @@ type Dirent struct {
} }
type Fsid struct { type Fsid struct {
_ [2]int32 X__val [2]int32
} }
type Flock_t struct { type Flock_t struct {
......
...@@ -219,7 +219,7 @@ func (b *B) run1() bool { ...@@ -219,7 +219,7 @@ func (b *B) run1() bool {
} }
// Only print the output if we know we are not going to proceed. // Only print the output if we know we are not going to proceed.
// Otherwise it is printed in processBench. // Otherwise it is printed in processBench.
if b.hasSub || b.finished { if atomic.LoadInt32(&b.hasSub) != 0 || b.finished {
tag := "BENCH" tag := "BENCH"
if b.skipped { if b.skipped {
tag = "SKIP" tag = "SKIP"
...@@ -460,10 +460,13 @@ func (ctx *benchContext) processBench(b *B) { ...@@ -460,10 +460,13 @@ func (ctx *benchContext) processBench(b *B) {
// //
// A subbenchmark is like any other benchmark. A benchmark that calls Run at // A subbenchmark is like any other benchmark. A benchmark that calls Run at
// least once will not be measured itself and will be called once with N=1. // least once will not be measured itself and will be called once with N=1.
//
// Run may be called simultaneously from multiple goroutines, but all such
// calls must happen before the outer benchmark function for b returns.
func (b *B) Run(name string, f func(b *B)) bool { func (b *B) Run(name string, f func(b *B)) bool {
// Since b has subbenchmarks, we will no longer run it as a benchmark itself. // Since b has subbenchmarks, we will no longer run it as a benchmark itself.
// Release the lock and acquire it on exit to ensure locks stay paired. // Release the lock and acquire it on exit to ensure locks stay paired.
b.hasSub = true atomic.StoreInt32(&b.hasSub, 1)
benchmarkLock.Unlock() benchmarkLock.Unlock()
defer benchmarkLock.Lock() defer benchmarkLock.Lock()
......
...@@ -6,6 +6,7 @@ package testing ...@@ -6,6 +6,7 @@ package testing
import ( import (
"bytes" "bytes"
"fmt"
"regexp" "regexp"
"strings" "strings"
"sync/atomic" "sync/atomic"
...@@ -515,3 +516,19 @@ func TestBenchmarkOutput(t *T) { ...@@ -515,3 +516,19 @@ func TestBenchmarkOutput(t *T) {
Benchmark(func(b *B) { b.Error("do not print this output") }) Benchmark(func(b *B) { b.Error("do not print this output") })
Benchmark(func(b *B) {}) Benchmark(func(b *B) {})
} }
func TestParallelSub(t *T) {
c := make(chan int)
block := make(chan int)
for i := 0; i < 10; i++ {
go func(i int) {
<-block
t.Run(fmt.Sprint(i), func(t *T) {})
c <- 1
}(i)
}
close(block)
for i := 0; i < 10; i++ {
<-c
}
}
...@@ -216,6 +216,7 @@ import ( ...@@ -216,6 +216,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
) )
...@@ -267,8 +268,8 @@ type common struct { ...@@ -267,8 +268,8 @@ type common struct {
skipped bool // Test of benchmark has been skipped. skipped bool // Test of benchmark has been skipped.
finished bool // Test function has completed. finished bool // Test function has completed.
done bool // Test is finished and all subtests have completed. done bool // Test is finished and all subtests have completed.
hasSub bool hasSub int32 // written atomically
raceErrors int // number of races detected during test raceErrors int // number of races detected during test
parent *common parent *common
level int // Nesting depth of test or benchmark. level int // Nesting depth of test or benchmark.
...@@ -645,7 +646,7 @@ func tRunner(t *T, fn func(t *T)) { ...@@ -645,7 +646,7 @@ func tRunner(t *T, fn func(t *T)) {
// Do not lock t.done to allow race detector to detect race in case // Do not lock t.done to allow race detector to detect race in case
// the user does not appropriately synchronizes a goroutine. // the user does not appropriately synchronizes a goroutine.
t.done = true t.done = true
if t.parent != nil && !t.hasSub { if t.parent != nil && atomic.LoadInt32(&t.hasSub) == 0 {
t.setRan() t.setRan()
} }
t.signal <- true t.signal <- true
...@@ -659,8 +660,11 @@ func tRunner(t *T, fn func(t *T)) { ...@@ -659,8 +660,11 @@ func tRunner(t *T, fn func(t *T)) {
// Run runs f as a subtest of t called name. It reports whether f succeeded. // Run runs f as a subtest of t called name. It reports whether f succeeded.
// Run will block until all its parallel subtests have completed. // Run will block until all its parallel subtests have completed.
//
// Run may be called simultaneously from multiple goroutines, but all such
// calls must happen before the outer test function for t returns.
func (t *T) Run(name string, f func(t *T)) bool { func (t *T) Run(name string, f func(t *T)) bool {
t.hasSub = true atomic.StoreInt32(&t.hasSub, 1)
testName, ok := t.context.match.fullName(&t.common, name) testName, ok := t.context.match.fullName(&t.common, name)
if !ok { if !ok {
return true return true
......
...@@ -54,9 +54,9 @@ ...@@ -54,9 +54,9 @@
ADCQ t3, h1; \ ADCQ t3, h1; \
ADCQ $0, h2 ADCQ $0, h2
DATA poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
DATA poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
GLOBL poly1305Mask<>(SB), RODATA, $16 GLOBL ·poly1305Mask<>(SB), RODATA, $16
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key) // func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
TEXT ·poly1305(SB), $0-32 TEXT ·poly1305(SB), $0-32
...@@ -67,8 +67,8 @@ TEXT ·poly1305(SB), $0-32 ...@@ -67,8 +67,8 @@ TEXT ·poly1305(SB), $0-32
MOVQ 0(AX), R11 MOVQ 0(AX), R11
MOVQ 8(AX), R12 MOVQ 8(AX), R12
ANDQ poly1305Mask<>(SB), R11 // r0 ANDQ ·poly1305Mask<>(SB), R11 // r0
ANDQ poly1305Mask<>+8(SB), R12 // r1 ANDQ ·poly1305Mask<>+8(SB), R12 // r1
XORQ R8, R8 // h0 XORQ R8, R8 // h0
XORQ R9, R9 // h1 XORQ R9, R9 // h1
XORQ R10, R10 // h2 XORQ R10, R10 // h2
......
...@@ -9,12 +9,12 @@ ...@@ -9,12 +9,12 @@
// This code was translated into a form compatible with 5a from the public // This code was translated into a form compatible with 5a from the public
// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. // domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
GLOBL poly1305_init_constants_armv6<>(SB), 8, $20 GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
// Warning: the linker may use R11 to synthesize certain instructions. Please // Warning: the linker may use R11 to synthesize certain instructions. Please
// take care and verify that no synthetic instructions use it. // take care and verify that no synthetic instructions use it.
...@@ -27,7 +27,7 @@ TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0 ...@@ -27,7 +27,7 @@ TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
ADD $4, R13, R8 ADD $4, R13, R8
MOVM.IB [R4-R7], (R8) MOVM.IB [R4-R7], (R8)
MOVM.IA.W (R1), [R2-R5] MOVM.IA.W (R1), [R2-R5]
MOVW $poly1305_init_constants_armv6<>(SB), R7 MOVW $·poly1305_init_constants_armv6<>(SB), R7
MOVW R2, R8 MOVW R2, R8
MOVW R2>>26, R9 MOVW R2>>26, R9
MOVW R3>>20, g MOVW R3>>20, g
......
// compile
// Copyright 2017 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 p
var (
e interface{}
s = struct{ a *int }{}
b = e == s
)
func test(obj interface{}) {
if obj != struct{ a *string }{} {
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment