diff options
author | Russ Cox <rsc@golang.org> | 2016-02-17 13:45:03 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2016-02-17 13:45:03 -0500 |
commit | 6e3041b92767ff38a993a265ef2daec64b3f7f11 (patch) | |
tree | 656b19140efdf0caba7bcefd38b1fc7f3f8b61c6 | |
parent | 5d343bdfb140970cc37f099064226d104ca6d817 (diff) | |
parent | 939a9424de5c3d0a0d2e1769778b5b0aa9c61954 (diff) | |
download | go-6e3041b92767ff38a993a265ef2daec64b3f7f11.tar.gz go-6e3041b92767ff38a993a265ef2daec64b3f7f11.zip |
all: merge master into release-branch.go1.6
Change-Id: Ie2a999e36ee654c1217bd03f720791360f66718d
88 files changed, 1054 insertions, 179 deletions
diff --git a/doc/asm.html b/doc/asm.html index 2af2005143..392af174c2 100644 --- a/doc/asm.html +++ b/doc/asm.html @@ -12,7 +12,7 @@ The document is not comprehensive. <p> The assembler is based on the input style of the Plan 9 assemblers, which is documented in detail -<a href="http://plan9.bell-labs.com/sys/doc/asm.html">elsewhere</a>. +<a href="https://9p.io/sys/doc/asm.html">elsewhere</a>. If you plan to write assembly language, you should read that document although much of it is Plan 9-specific. The current document provides a summary of the syntax and the differences with what is explained in that document, and @@ -23,7 +23,7 @@ describes the peculiarities that apply when writing assembly code to interact wi The most important thing to know about Go's assembler is that it is not a direct representation of the underlying machine. Some of the details map precisely to the machine, but some do not. This is because the compiler suite (see -<a href="http://plan9.bell-labs.com/sys/doc/compiler.html">this description</a>) +<a href="https://9p.io/sys/doc/compiler.html">this description</a>) needs no assembler pass in the usual pipeline. Instead, the compiler operates on a kind of semi-abstract instruction set, and instruction selection occurs partly after code generation. @@ -621,6 +621,15 @@ These modes accept only 1, 2, 4, and 8 as scale factors. </ul> +<p> +When using the compiler and assembler's +<code>-dynlink</code> or <code>-shared</code> modes, +any load or store of a fixed memory location such as a global variable +must be assumed to overwrite <code>CX</code>. +Therefore, to be safe for use with these modes, +assembly sources should typically avoid CX except between memory references. +</p> + <h3 id="amd64">64-bit Intel 386 (a.k.a. amd64)</h3> <p> diff --git a/doc/codewalk/codewalk.xml b/doc/codewalk/codewalk.xml index 3496db71d7..34e6e91938 100644 --- a/doc/codewalk/codewalk.xml +++ b/doc/codewalk/codewalk.xml @@ -91,7 +91,7 @@ The full address syntax is summarized in this table (an excerpt of Table II from - <a href="http://plan9.bell-labs.com/sys/doc/sam/sam.html">The text editor <code>sam</code></a>): + <a href="https://9p.io/sys/doc/sam/sam.html">The text editor <code>sam</code></a>): <br/><br/> <table> diff --git a/doc/contribute.html b/doc/contribute.html index a321a8646f..4619c81124 100644 --- a/doc/contribute.html +++ b/doc/contribute.html @@ -198,9 +198,13 @@ prints help text, not an error. </p> <p> -Note to Git aficionados: The <code>git-codereview</code> command is not required to +<b>Note to Git aficionados:</b> +The <code>git-codereview</code> command is not required to upload and manage Gerrit code reviews. For those who prefer plain Git, the text -below gives the Git equivalent of each git-codereview command. If you do use plain +below gives the Git equivalent of each git-codereview command. +</p> + +<p>If you do use plain Git, note that you still need the commit hooks that the git-codereview command configures; those hooks add a Gerrit <code>Change-Id</code> line to the commit message and check that all Go source files have been formatted with gofmt. Even @@ -208,6 +212,12 @@ if you intend to use plain Git for daily work, install the hooks in a new Git checkout by running <code>git-codereview</code> <code>hooks</code>. </p> +<p> +The workflow described below assumes a single change per branch. +It is also possible to prepare a sequence of (usually related) changes in a single branch. +See the <a href="https://golang.org/x/review/git-codereview">git-codereview documentation</a> for details. +</p> + <h3 id="git-config">Set up git aliases</h3> <p> diff --git a/doc/go1.6.html b/doc/go1.6.html index b4a3900aa0..17c3536aeb 100644 --- a/doc/go1.6.html +++ b/doc/go1.6.html @@ -1,5 +1,5 @@ <!--{ - "Title": "Go 1.6 Release Notes DRAFT", + "Title": "Go 1.6 Release Notes", "Path": "/doc/go1.6", "Template": true }--> @@ -13,13 +13,6 @@ Edit .,s;^([a-z][A-Za-z0-9_/]+)\.([A-Z][A-Za-z0-9_]+\.)?([A-Z][A-Za-z0-9_]+)([ . ul li { margin: 0.5em 0; } </style> -<p> -<i>NOTE: This is a DRAFT of the Go 1.6 release notes, prepared for the Go 1.6 beta. -Go 1.6 has NOT yet been released. -By our regular schedule, it is expected some time in February 2016. -</i> -</p> - <h2 id="introduction">Introduction to Go 1.6</h2> <p> @@ -70,9 +63,12 @@ On NaCl, Go 1.5 required SDK version pepper-41. Go 1.6 adds support for later SDK versions. </p> -<pre> -TODO: CX no longer available on 386 assembly? (https://golang.org/cl/16386) -</pre> +<p> +On 32-bit x86 systems using the <code>-dynlink</code> or <code>-shared</code> compilation modes, +the register CX is now overwritten by certain memory references and should +be avoided in hand-written assembly. +See the <a href="/doc/asm#x86">assembly documentation</a> for details. +</p> <h2 id="tools">Tools</h2> @@ -248,7 +244,7 @@ Some programs may run faster, some slower. On average the programs in the Go 1 benchmark suite run a few percent faster in Go 1.6 than they did in Go 1.5. The garbage collector's pauses are even lower than in Go 1.5, -although the effect is likely only noticeable for programs using +especially for programs using a large amount of memory. </p> @@ -569,7 +565,7 @@ The <a href="/pkg/debug/elf/"><code>debug/elf</code></a> package adds support for general compressed ELF sections. User code needs no updating: the sections are decompressed automatically when read. However, compressed -<a href="/pkg/debug/elf/#Section"><code>Section</code></a>'s do not support random access: +<a href="/pkg/debug/elf/#Section"><code>Sections</code></a> do not support random access: they have a nil <code>ReaderAt</code> field. </li> @@ -632,7 +628,6 @@ In previous releases, the argument to <code>*</code> was required to have type < Also in the <a href="/pkg/fmt/"><code>fmt</code></a> package, <a href="/pkg/fmt/#Scanf"><code>Scanf</code></a> can now scan hexadecimal strings using %X, as an alias for %x. Both formats accept any mix of upper- and lower-case hexadecimal. -<a href="https://golang.org/issues/13585">TODO: Keep?</a> </li> <li> @@ -717,9 +712,6 @@ Second, DNS lookup functions such as <a href="/pkg/net/#LookupAddr"><code>LookupAddr</code></a> now return rooted domain names (with a trailing dot) on Plan 9 and Windows, to match the behavior of Go on Unix systems. -TODO: Third, lookups satisfied from /etc/hosts now add a trailing dot as well, -so that looking up 127.0.0.1 typically now returns “localhost.” not “localhost”. -This is arguably a mistake but is not yet fixed. See https://golang.org/issue/13564. </li> <li> @@ -875,16 +867,18 @@ should only be used when contention has been observed. <li> The <a href="/pkg/strconv/"><code>strconv</code></a> package adds <a href="/pkg/strconv/#IsGraphic"><code>IsGraphic</code></a>, +similar to <a href="/pkg/strconv/#IsPrint"><code>IsPrint</code></a>. +It also adds <a href="/pkg/strconv/#QuoteToGraphic"><code>QuoteToGraphic</code></a>, <a href="/pkg/strconv/#QuoteRuneToGraphic"><code>QuoteRuneToGraphic</code></a>, <a href="/pkg/strconv/#AppendQuoteToGraphic"><code>AppendQuoteToGraphic</code></a>, and <a href="/pkg/strconv/#AppendQuoteRuneToGraphic"><code>AppendQuoteRuneToGraphic</code></a>, analogous to -<a href="/pkg/strconv/#IsPrint"><code>IsPrint</code></a>, -<a href="/pkg/strconv/#QuoteToPrint"><code>QuoteToPrint</code></a>, +<a href="/pkg/strconv/#QuoteToASCII"><code>QuoteToASCII</code></a>, +<a href="/pkg/strconv/#QuoteRuneToASCII"><code>QuoteRuneToASCII</code></a>, and so on. -The <code>Print</code> family escapes all space characters except ASCII space (U+0020). +The <code>ASCII</code> family escapes all space characters except ASCII space (U+0020). In contrast, the <code>Graphic</code> family does not escape any Unicode space characters (category Zs). </li> diff --git a/doc/go_faq.html b/doc/go_faq.html index bcd12075b6..b5f9772787 100644 --- a/doc/go_faq.html +++ b/doc/go_faq.html @@ -98,7 +98,7 @@ What's the origin of the mascot?</h3> <p> The mascot and logo were designed by <a href="http://reneefrench.blogspot.com">Renée French</a>, who also designed -<a href="http://plan9.bell-labs.com/plan9/glenda.html">Glenda</a>, +<a href="https://9p.io/plan9/glenda.html">Glenda</a>, the Plan 9 bunny. The <a href="https://blog.golang.org/gopher">gopher</a> is derived from one she used for an <a href="http://wfmu.org/">WFMU</a> diff --git a/misc/nacl/testzip.proto b/misc/nacl/testzip.proto index c8ab18ea20..4e82ac9b4b 100644 --- a/misc/nacl/testzip.proto +++ b/misc/nacl/testzip.proto @@ -27,23 +27,23 @@ go src=.. internal objfile objfile.go + unvendor + golang.org + x + arch + arm + armasm + testdata + + + x86 + x86asm + testdata + + gofmt gofmt.go gofmt_test.go testdata + - vendor - golang.org - x - arch - arm - armasm - testdata - + - x86 - x86asm - testdata - + archive tar testdata diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index 64b6e36758..d00e5a6c46 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -748,7 +748,13 @@ func typefmt(t *Type, flag int) string { if name != "" { str = name + " " + typ } - if flag&obj.FmtShort == 0 && !fmtbody && t.Note != nil { + + // The fmtbody flag is intended to suppress escape analysis annotations + // when printing a function type used in a function body. + // (The escape analysis tags do not apply to func vars.) + // But it must not suppress struct field tags. + // See golang.org/issue/13777 and golang.org/issue/14331. + if flag&obj.FmtShort == 0 && (!fmtbody || !t.Funarg) && t.Note != nil { str += " " + strconv.Quote(*t.Note) } return str diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index 836834f8bd..b756055668 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -836,7 +836,7 @@ func gen(n *Node) { Cgen_as_wb(n.Left, n.Right, true) case OAS2DOTTYPE: - cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, false) + cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, needwritebarrier(n.List.N, n.Rlist.N)) case OCALLMETH: cgen_callmeth(n, 0) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 156b868109..36c829d1b9 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -947,6 +947,11 @@ func (t *tester) raceTest(dt *distTest) error { t.addCmd(dt, "src", "go", "test", "-race", "-i", "runtime/race", "flag", "os/exec") t.addCmd(dt, "src", "go", "test", "-race", "-run=Output", "runtime/race") t.addCmd(dt, "src", "go", "test", "-race", "-short", "-run=TestParse|TestEcho", "flag", "os/exec") + // We don't want the following line, because it + // slows down all.bash (by 10 seconds on my laptop). + // The race builder should catch any error here, but doesn't. + // TODO(iant): Figure out how to catch this. + // t.addCmd(dt, "src", "go", "test", "-race", "-run=TestParallelTest", "cmd/go") if t.cgoEnabled { env := mergeEnvLists([]string{"GOTRACEBACK=2"}, os.Environ()) cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", "-race", "-short") diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index a1f925ed0b..f2a2a6014f 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -667,6 +667,7 @@ var ( goarch string goos string exeSuffix string + gopath []string ) func init() { @@ -675,6 +676,7 @@ func init() { if goos == "windows" { exeSuffix = ".exe" } + gopath = filepath.SplitList(buildContext.GOPATH) } // A builder holds global state about a build. @@ -1684,6 +1686,22 @@ func (b *builder) includeArgs(flag string, all []*action) []string { inc = append(inc, flag, b.work) // Finally, look in the installed package directories for each action. + // First add the package dirs corresponding to GOPATH entries + // in the original GOPATH order. + need := map[string]*build.Package{} + for _, a1 := range all { + if a1.p != nil && a1.pkgdir == a1.p.build.PkgRoot { + need[a1.p.build.Root] = a1.p.build + } + } + for _, root := range gopath { + if p := need[root]; p != nil && !incMap[p.PkgRoot] { + incMap[p.PkgRoot] = true + inc = append(inc, flag, p.PkgTargetRoot) + } + } + + // Then add anything that's left. for _, a1 := range all { if a1.p == nil { continue diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 6d12f75073..39e0f3e56d 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -10,6 +10,7 @@ import ( "fmt" "go/build" "go/format" + "internal/race" "internal/testenv" "io" "io/ioutil" @@ -69,7 +70,11 @@ func TestMain(m *testing.M) { flag.Parse() if canRun { - out, err := exec.Command("go", "build", "-tags", "testgo", "-o", "testgo"+exeSuffix).CombinedOutput() + args := []string{"build", "-tags", "testgo", "-o", "testgo" + exeSuffix} + if race.Enabled { + args = append(args, "-race") + } + out, err := exec.Command("go", args...).CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out) os.Exit(2) @@ -2565,6 +2570,59 @@ func TestGoInstallShadowedGOPATH(t *testing.T) { tg.grepStderr("no install location for.*gopath2.src.test: hidden by .*gopath1.src.test", "missing error") } +func TestGoBuildGOPATHOrder(t *testing.T) { + // golang.org/issue/14176#issuecomment-179895769 + // golang.org/issue/14192 + // -I arguments to compiler could end up not in GOPATH order, + // leading to unexpected import resolution in the compiler. + // This is still not a complete fix (see golang.org/issue/14271 and next test) + // but it is clearly OK and enough to fix both of the two reported + // instances of the underlying problem. It will have to do for now. + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path("p1")+string(filepath.ListSeparator)+tg.path("p2")) + + tg.tempFile("p1/src/foo/foo.go", "package foo\n") + tg.tempFile("p2/src/baz/baz.go", "package baz\n") + tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n") + tg.tempFile("p1/src/bar/bar.go", ` + package bar + import _ "baz" + import _ "foo" + `) + + tg.run("install", "-x", "bar") +} + +func TestGoBuildGOPATHOrderBroken(t *testing.T) { + // This test is known not to work. + // See golang.org/issue/14271. + t.Skip("golang.org/issue/14271") + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + + tg.tempFile("p1/src/foo/foo.go", "package foo\n") + tg.tempFile("p2/src/baz/baz.go", "package baz\n") + tg.tempFile("p1/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/baz.a", "bad\n") + tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n") + tg.tempFile("p1/src/bar/bar.go", ` + package bar + import _ "baz" + import _ "foo" + `) + + colon := string(filepath.ListSeparator) + tg.setenv("GOPATH", tg.path("p1")+colon+tg.path("p2")) + tg.run("install", "-x", "bar") + + tg.setenv("GOPATH", tg.path("p2")+colon+tg.path("p1")) + tg.run("install", "-x", "bar") +} + func TestIssue11709(t *testing.T) { tg := testgo(t) defer tg.cleanup() @@ -2682,3 +2740,22 @@ func TestIssue13655(t *testing.T) { tg.grepStdout("runtime/internal/sys", "did not find required dependency of "+pkg+" on runtime/internal/sys") } } + +// For issue 14337. +func TestParallelTest(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + const testSrc = `package package_test + import ( + "testing" + ) + func TestTest(t *testing.T) { + }` + tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1)) + tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1)) + tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1)) + tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1)) + tg.setenv("GOPATH", tg.path(".")) + tg.run("test", "-p=4", "p1", "p2", "p3", "p4") +} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index d384594722..f9b979da7f 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -454,7 +454,9 @@ func envForDir(dir string, base []string) []string { // mergeEnvLists merges the two environment lists such that // variables with the same name in "in" replace those in "out". +// This always returns a newly allocated slice. func mergeEnvLists(in, out []string) []string { + out = append([]string(nil), out...) NextVar: for _, inkv := range in { k := strings.SplitAfterN(inkv, "=", 2)[0] diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go index a804ccd277..0c0cf07e71 100644 --- a/src/cmd/go/pkg.go +++ b/src/cmd/go/pkg.go @@ -967,7 +967,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package } } } - if p.Standard && !p1.Standard && p.Error == nil { + if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil { p.Error = &PackageError{ ImportStack: stk.copy(), Err: fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath), diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go index 6495dfb356..f038883dc0 100644 --- a/src/cmd/internal/objfile/disasm.go +++ b/src/cmd/internal/objfile/disasm.go @@ -15,8 +15,8 @@ import ( "strings" "text/tabwriter" - "golang.org/x/arch/arm/armasm" - "golang.org/x/arch/x86/x86asm" + "cmd/internal/unvendor/golang.org/x/arch/arm/armasm" + "cmd/internal/unvendor/golang.org/x/arch/x86/x86asm" ) // Disasm is a disassembler for a given File. diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile index a3f57001f6..a3f57001f6 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/Makefile +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go index 6b4d73841b..6b4d73841b 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go index e2d9127348..e2d9127348 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go index 98192b324e..98192b324e 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go index 1a97a5a844..1a97a5a844 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go index 60d633bdb6..60d633bdb6 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdump_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go index db51902cc7..db51902cc7 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdump_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go index 74fb47d2db..74fb47d2db 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/plan9x.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go index fae0ca62a5..fae0ca62a5 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/plan9x.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/tables.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go index 58f51fe1f5..58f51fe1f5 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/tables.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile index 1adab68517..1adab68517 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/Makefile +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt index cc1ea0abe5..cc1ea0abe5 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile index 9eb4557c11..9eb4557c11 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/Makefile +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go index e4122c1e6d..e4122c1e6d 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go index b6098b898e..b6098b898e 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go index eadfd71bf5..eadfd71bf5 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go index e2ff801183..e2ff801183 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go index ef74025e08..ef74025e08 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go index 23ac523207..23ac523207 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go index 90af9dd638..90af9dd638 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdump_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go index 3d4e1460f8..3d4e1460f8 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdump_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go index f720dc6cb7..f720dc6cb7 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go index 9bd296cf75..9bd296cf75 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go index afe6a92e90..afe6a92e90 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go index f2ea28cd90..f2ea28cd90 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/tables.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go index 3d08d5ebe3..3d08d5ebe3 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/tables.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile index 9cb44127a4..9cb44127a4 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt index a899d75fdb..a899d75fdb 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c index 90ace5241d..90ace5241d 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xed_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go index 91cf822727..91cf822727 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xed_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xedext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go index e27cdc07c4..e27cdc07c4 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xedext_test.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go diff --git a/src/cmd/vendor/vendor.json b/src/cmd/internal/unvendor/vendor.json index 565498ff8a..565498ff8a 100644 --- a/src/cmd/vendor/vendor.json +++ b/src/cmd/internal/unvendor/vendor.json diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 563600d9a2..a96b37a4be 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1946,7 +1946,9 @@ func writepub(ispub func(*DWDie) bool) int64 { */ func writearanges() int64 { sectionstart := Cpos() - headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize))) // don't count unit_length field itself + // The first tuple is aligned to a multiple of the size of a single tuple + // (twice the size of an address) + headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize*2))) // don't count unit_length field itself for compunit := dwroot.child; compunit != nil; compunit = compunit.link { b := getattr(compunit, DW_AT_low_pc) diff --git a/src/go/constant/value.go b/src/go/constant/value.go index 630581047a..310814df71 100644 --- a/src/go/constant/value.go +++ b/src/go/constant/value.go @@ -96,7 +96,7 @@ func (x stringVal) String() string { // only the first maxLen-3 runes; then add "...". i := 0 for n := 0; n < maxLen-3; n++ { - _, size := utf8.DecodeRuneInString(s) + _, size := utf8.DecodeRuneInString(s[i:]) i += size } s = s[:i] + "..." diff --git a/src/go/constant/value_test.go b/src/go/constant/value_test.go index de1ab0267a..dbd96c07a3 100644 --- a/src/go/constant/value_test.go +++ b/src/go/constant/value_test.go @@ -204,6 +204,7 @@ func eql(x, y Value) bool { // String tests var xxx = strings.Repeat("x", 68) +var issue14262 = `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل). المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد لهذا الترخيص."` var stringTests = []struct { input, short, exact string @@ -225,6 +226,7 @@ var stringTests = []struct { {`"` + xxx + `xx"`, `"` + xxx + `xx"`, `"` + xxx + `xx"`}, {`"` + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + `xxx"`}, {`"` + xxx + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + xxx + `xxx"`}, + {issue14262, `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة ال...`, issue14262}, // Int {"0", "0", "0"}, diff --git a/src/go/internal/gcimporter/gcimporter.go b/src/go/internal/gcimporter/gcimporter.go index 0ef8eb4fc6..d70ec083c3 100644 --- a/src/go/internal/gcimporter/gcimporter.go +++ b/src/go/internal/gcimporter/gcimporter.go @@ -31,7 +31,8 @@ var pkgExts = [...]string{".a", ".o"} // FindPkg returns the filename and unique package id for an import // path based on package information provided by build.Import (using -// the build.Default build.Context). +// the build.Default build.Context). A relative srcDir is interpreted +// relative to the current working directory. // If no file was found, an empty filename is returned. // func FindPkg(path, srcDir string) (filename, id string) { @@ -44,6 +45,9 @@ func FindPkg(path, srcDir string) (filename, id string) { default: // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" // Don't require the source files to be present. + if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 + srcDir = abs + } bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) if bp.PkgObj == "" { return diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 942d3fd5f7..f7c4a17378 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -184,7 +184,8 @@ func roundFloat64(x constant.Value) constant.Value { // provided (only needed for int/uint sizes). // // If rounded != nil, *rounded is set to the rounded value of x for -// representable floating-point values; it is left alone otherwise. +// representable floating-point and complex values, and to an Int +// value for integer values; it is left alone otherwise. // It is ok to provide the addressof the first argument for rounded. func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *constant.Value) bool { if x.Kind() == constant.Unknown { @@ -197,6 +198,9 @@ func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *con if x.Kind() != constant.Int { return false } + if rounded != nil { + *rounded = x + } if x, ok := constant.Int64Val(x); ok { switch typ.kind { case Int: @@ -808,8 +812,6 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o typ := x.typ.Underlying().(*Basic) // force integer division of integer operands if op == token.QUO && isInteger(typ) { - xval = constant.ToInt(xval) - yval = constant.ToInt(yval) op = token.QUO_ASSIGN } x.val = constant.BinaryOp(xval, op, yval) diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 14148a585b..1536df5bf1 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -483,11 +483,9 @@ func pkgName(path string) string { // (Per the go/build package dependency tests, we cannot import // path/filepath and simply use filepath.Dir.) func dir(path string) string { - if i := strings.LastIndexAny(path, "/\\"); i >= 0 { - path = path[:i] + if i := strings.LastIndexAny(path, `/\`); i > 0 { + return path[:i] } - if path == "" { - path = "." - } - return path + // i <= 0 + return "." } diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src index 564d0649b2..4fe0c62938 100644 --- a/src/go/types/testdata/issues.src +++ b/src/go/types/testdata/issues.src @@ -153,3 +153,20 @@ func issue10260() { make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */ make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */ } + +// Check that constants representable as integers are in integer form +// before being used in operations that are only defined on integers. +func issue14229() { + // from the issue + const _ = int64(-1<<63) % 1e6 + + // related + const ( + a int = 3 + b = 4.0 + _ = a / b + _ = a % b + _ = b / a + _ = b % a + ) +} diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 11f33cf3b1..4e19b3e71f 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1,5 +1,5 @@ -// Code generated by golang.org/x/tools/cmd/bundle command: -// $ bundle golang.org/x/net/http2 net/http http2 +// Code generated by golang.org/x/tools/cmd/bundle. +//go:generate bundle -o h2_bundle.go -prefix http2 -import golang.org/x/net/http2/hpack=internal/golang.org/x/net/http2/hpack golang.org/x/net/http2 // Package http2 implements the HTTP/2 protocol. // @@ -2331,6 +2331,10 @@ var http2isTokenTable = [127]bool{ '~': true, } +type http2connectionStater interface { + ConnectionState() tls.ConnectionState +} + // pipe is a goroutine-safe io.Reader/io.Writer pair. It's like // io.Pipe except there are no PipeReader/PipeWriter halves, and the // underlying buffer is an interface. (io.Pipe is always unbuffered) @@ -2593,28 +2597,76 @@ func http2ConfigureServer(s *Server, conf *http2Server) error { if http2testHookOnConn != nil { http2testHookOnConn() } - conf.handleConn(hs, c, h) + conf.ServeConn(c, &http2ServeConnOpts{ + Handler: h, + BaseConfig: hs, + }) } s.TLSNextProto[http2NextProtoTLS] = protoHandler s.TLSNextProto["h2-14"] = protoHandler return nil } -func (srv *http2Server) handleConn(hs *Server, c net.Conn, h Handler) { +// ServeConnOpts are options for the Server.ServeConn method. +type http2ServeConnOpts struct { + // BaseConfig optionally sets the base configuration + // for values. If nil, defaults are used. + BaseConfig *Server + + // Handler specifies which handler to use for processing + // requests. If nil, BaseConfig.Handler is used. If BaseConfig + // or BaseConfig.Handler is nil, http.DefaultServeMux is used. + Handler Handler +} + +func (o *http2ServeConnOpts) baseConfig() *Server { + if o != nil && o.BaseConfig != nil { + return o.BaseConfig + } + return new(Server) +} + +func (o *http2ServeConnOpts) handler() Handler { + if o != nil { + if o.Handler != nil { + return o.Handler + } + if o.BaseConfig != nil && o.BaseConfig.Handler != nil { + return o.BaseConfig.Handler + } + } + return DefaultServeMux +} + +// ServeConn serves HTTP/2 requests on the provided connection and +// blocks until the connection is no longer readable. +// +// ServeConn starts speaking HTTP/2 assuming that c has not had any +// reads or writes. It writes its initial settings frame and expects +// to be able to read the preface and settings frame from the +// client. If c has a ConnectionState method like a *tls.Conn, the +// ConnectionState is used to verify the TLS ciphersuite and to set +// the Request.TLS field in Handlers. +// +// ServeConn does not support h2c by itself. Any h2c support must be +// implemented in terms of providing a suitably-behaving net.Conn. +// +// The opts parameter is optional. If nil, default values are used. +func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) { sc := &http2serverConn{ - srv: srv, - hs: hs, + srv: s, + hs: opts.baseConfig(), conn: c, remoteAddrStr: c.RemoteAddr().String(), bw: http2newBufferedWriter(c), - handler: h, + handler: opts.handler(), streams: make(map[uint32]*http2stream), readFrameCh: make(chan http2readFrameResult), wantWriteFrameCh: make(chan http2frameWriteMsg, 8), wroteFrameCh: make(chan http2frameWriteResult, 1), bodyReadCh: make(chan http2bodyReadMsg), doneServing: make(chan struct{}), - advMaxStreams: srv.maxConcurrentStreams(), + advMaxStreams: s.maxConcurrentStreams(), writeSched: http2writeScheduler{ maxFrameSize: http2initialMaxFrameSize, }, @@ -2630,10 +2682,10 @@ func (srv *http2Server) handleConn(hs *Server, c net.Conn, h Handler) { sc.hpackDecoder.SetMaxStringLength(sc.maxHeaderStringLen()) fr := http2NewFramer(sc.bw, c) - fr.SetMaxReadFrameSize(srv.maxReadFrameSize()) + fr.SetMaxReadFrameSize(s.maxReadFrameSize()) sc.framer = fr - if tc, ok := c.(*tls.Conn); ok { + if tc, ok := c.(http2connectionStater); ok { sc.tlsState = new(tls.ConnectionState) *sc.tlsState = tc.ConnectionState() @@ -2646,7 +2698,7 @@ func (srv *http2Server) handleConn(hs *Server, c net.Conn, h Handler) { } - if !srv.PermitProhibitedCipherSuites && http2isBadCipher(sc.tlsState.CipherSuite) { + if !s.PermitProhibitedCipherSuites && http2isBadCipher(sc.tlsState.CipherSuite) { sc.rejectConn(http2ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite)) return @@ -4874,10 +4926,7 @@ func (t *http2Transport) NewClientConn(c net.Conn) (*http2ClientConn, error) { cc.henc = hpack.NewEncoder(&cc.hbuf) - type connectionStater interface { - ConnectionState() tls.ConnectionState - } - if cs, ok := c.(connectionStater); ok { + if cs, ok := c.(http2connectionStater); ok { state := cs.ConnectionState() cc.tlsState = &state } @@ -5028,7 +5077,27 @@ func (cc *http2ClientConn) responseHeaderTimeout() time.Duration { return 0 } +// checkConnHeaders checks whether req has any invalid connection-level headers. +// per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields. +// Certain headers are special-cased as okay but not transmitted later. +func http2checkConnHeaders(req *Request) error { + if v := req.Header.Get("Upgrade"); v != "" { + return errors.New("http2: invalid Upgrade request header") + } + if v := req.Header.Get("Transfer-Encoding"); (v != "" && v != "chunked") || len(req.Header["Transfer-Encoding"]) > 1 { + return errors.New("http2: invalid Transfer-Encoding request header") + } + if v := req.Header.Get("Connection"); (v != "" && v != "close" && v != "keep-alive") || len(req.Header["Connection"]) > 1 { + return errors.New("http2: invalid Connection request header") + } + return nil +} + func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { + if err := http2checkConnHeaders(req); err != nil { + return nil, err + } + trailers, err := http2commaSeparatedTrailers(req) if err != nil { return nil, err @@ -5334,10 +5403,14 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail var didUA bool for k, vv := range req.Header { lowKey := strings.ToLower(k) - if lowKey == "host" || lowKey == "content-length" { + switch lowKey { + case "host", "content-length": + continue - } - if lowKey == "user-agent" { + case "connection", "proxy-connection", "transfer-encoding", "upgrade": + + continue + case "user-agent": didUA = true if len(vv) < 1 { @@ -5445,8 +5518,9 @@ func (cc *http2ClientConn) streamByID(id uint32, andRemove bool) *http2clientStr // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop. type http2clientConnReadLoop struct { - cc *http2ClientConn - activeRes map[uint32]*http2clientStream // keyed by streamID + cc *http2ClientConn + activeRes map[uint32]*http2clientStream // keyed by streamID + closeWhenIdle bool hdec *hpack.Decoder @@ -5503,7 +5577,7 @@ func (rl *http2clientConnReadLoop) cleanup() { func (rl *http2clientConnReadLoop) run() error { cc := rl.cc - closeWhenIdle := cc.t.disableKeepAlives() + rl.closeWhenIdle = cc.t.disableKeepAlives() gotReply := false for { f, err := cc.fr.ReadFrame() @@ -5552,7 +5626,7 @@ func (rl *http2clientConnReadLoop) run() error { if err != nil { return err } - if closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 { + if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 { cc.closeIfIdle() } } @@ -5803,6 +5877,9 @@ func (rl *http2clientConnReadLoop) endStream(cs *http2clientStream) { } cs.bufPipe.closeWithErrorAndCode(err, code) delete(rl.activeRes, cs.ID) + if cs.req.Close || cs.req.Header.Get("Connection") == "close" { + rl.closeWhenIdle = true + } } func (cs *http2clientStream) copyTrailers() { @@ -6064,13 +6141,18 @@ func (rt http2erringRoundTripper) RoundTrip(*Request) (*Response, error) { retur // call gzip.NewReader on the first call to Read type http2gzipReader struct { body io.ReadCloser // underlying Response.Body - zr io.Reader // lazily-initialized gzip reader + zr *gzip.Reader // lazily-initialized gzip reader + zerr error // sticky error } func (gz *http2gzipReader) Read(p []byte) (n int, err error) { + if gz.zerr != nil { + return 0, gz.zerr + } if gz.zr == nil { gz.zr, err = gzip.NewReader(gz.body) if err != nil { + gz.zerr = err return 0, err } } diff --git a/src/net/http/httptest/server.go b/src/net/http/httptest/server.go index fabfeca943..a2573df251 100644 --- a/src/net/http/httptest/server.go +++ b/src/net/http/httptest/server.go @@ -202,10 +202,31 @@ func (s *Server) logCloseHangDebugInfo() { // CloseClientConnections closes any open HTTP connections to the test Server. func (s *Server) CloseClientConnections() { + var conns int + ch := make(chan bool) + s.mu.Lock() - defer s.mu.Unlock() for c := range s.conns { - s.closeConn(c) + conns++ + s.closeConnChan(c, ch) + } + s.mu.Unlock() + + // Wait for outstanding closes to finish. + // + // Out of paranoia for making a late change in Go 1.6, we + // bound how long this can wait, since golang.org/issue/14291 + // isn't fully understood yet. At least this should only be used + // in tests. + timer := time.NewTimer(5 * time.Second) + defer timer.Stop() + for i := 0; i < conns; i++ { + select { + case <-ch: + case <-timer.C: + // Too slow. Give up. + return + } } } @@ -267,9 +288,13 @@ func (s *Server) wrap() { } } -// closeConn closes c. Except on plan9, which is special. See comment below. +// closeConn closes c. // s.mu must be held. -func (s *Server) closeConn(c net.Conn) { +func (s *Server) closeConn(c net.Conn) { s.closeConnChan(c, nil) } + +// closeConnChan is like closeConn, but takes an optional channel to receive a value +// when the goroutine closing c is done. +func (s *Server) closeConnChan(c net.Conn, done chan<- bool) { if runtime.GOOS == "plan9" { // Go's Plan 9 net package isn't great at unblocking reads when // their underlying TCP connections are closed. Don't trust @@ -278,7 +303,21 @@ func (s *Server) closeConn(c net.Conn) { // resources if the syscall doesn't end up returning. Oh well. s.forgetConn(c) } - go c.Close() + + // Somewhere in the chaos of https://golang.org/cl/15151 we found that + // some types of conns were blocking in Close too long (or deadlocking?) + // and we had to call Close in a goroutine. I (bradfitz) forget what + // that was at this point, but I suspect it was *tls.Conns, which + // were later fixed in https://golang.org/cl/18572, so this goroutine + // is _probably_ unnecessary now. But it's too late in Go 1.6 too remove + // it with confidence. + // TODO(bradfitz): try to remove it for Go 1.7. (golang.org/issue/14291) + go func() { + c.Close() + if done != nil { + done <- true + } + }() } // forgetConn removes c from the set of tracked conns and decrements it from the diff --git a/src/net/http/httptest/server_test.go b/src/net/http/httptest/server_test.go index 6ffc671e57..c9606f2419 100644 --- a/src/net/http/httptest/server_test.go +++ b/src/net/http/httptest/server_test.go @@ -84,3 +84,17 @@ func TestServerCloseBlocking(t *testing.T) { ts.Close() // test we don't hang here forever. } + +// Issue 14290 +func TestServerCloseClientConnections(t *testing.T) { + var s *Server + s = NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.CloseClientConnections() + })) + defer s.Close() + res, err := http.Get(s.URL) + if err == nil { + res.Body.Close() + t.Fatal("Unexpected response: %#v", res) + } +} diff --git a/src/net/http/request.go b/src/net/http/request.go index 16c5bb43ac..8cdab02af5 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -99,30 +99,37 @@ type Request struct { ProtoMajor int // 1 ProtoMinor int // 0 - // A header maps request lines to their values. - // If the header says + // Header contains the request header fields either received + // by the server or to be sent by the client. // + // If a server received a request with header lines, + // + // Host: example.com // accept-encoding: gzip, deflate // Accept-Language: en-us - // Connection: keep-alive + // fOO: Bar + // foo: two // // then // // Header = map[string][]string{ // "Accept-Encoding": {"gzip, deflate"}, // "Accept-Language": {"en-us"}, - // "Connection": {"keep-alive"}, + // "Foo": {"Bar", "two"}, // } // - // HTTP defines that header names are case-insensitive. - // The request parser implements this by canonicalizing the - // name, making the first character and any characters - // following a hyphen uppercase and the rest lowercase. + // For incoming requests, the Host header is promoted to the + // Request.Host field and removed from the Header map. // - // For client requests certain headers are automatically - // added and may override values in Header. + // HTTP defines that header names are case-insensitive. The + // request parser implements this by using CanonicalHeaderKey, + // making the first character and any characters following a + // hyphen uppercase and the rest lowercase. // - // See the documentation for the Request.Write method. + // For client requests, certain headers such as Content-Length + // and Connection are automatically written when needed and + // values in Header may be ignored. See the documentation + // for the Request.Write method. Header Header // Body is the request's body. @@ -152,8 +159,15 @@ type Request struct { TransferEncoding []string // Close indicates whether to close the connection after - // replying to this request (for servers) or after sending - // the request (for clients). + // replying to this request (for servers) or after sending this + // request and reading its response (for clients). + // + // For server requests, the HTTP server handles this automatically + // and this field is not needed by Handlers. + // + // For client requests, setting this field prevents re-use of + // TCP connections between requests to the same hosts, as if + // Transport.DisableKeepAlives were set. Close bool // For server requests Host specifies the host on which the diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index f8cad802d4..384b453ce0 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -1039,12 +1039,30 @@ func TestAutomaticHTTP2_Serve(t *testing.T) { } func TestAutomaticHTTP2_ListenAndServe(t *testing.T) { - defer afterTest(t) - defer SetTestHookServerServe(nil) cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) if err != nil { t.Fatal(err) } + testAutomaticHTTP2_ListenAndServe(t, &tls.Config{ + Certificates: []tls.Certificate{cert}, + }) +} + +func TestAutomaticHTTP2_ListenAndServe_GetCertificate(t *testing.T) { + cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + if err != nil { + t.Fatal(err) + } + testAutomaticHTTP2_ListenAndServe(t, &tls.Config{ + GetCertificate: func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { + return &cert, nil + }, + }) +} + +func testAutomaticHTTP2_ListenAndServe(t *testing.T, tlsConf *tls.Config) { + defer afterTest(t) + defer SetTestHookServerServe(nil) var ok bool var s *Server const maxTries = 5 @@ -1060,10 +1078,8 @@ Try: lnc <- ln }) s = &Server{ - Addr: addr, - TLSConfig: &tls.Config{ - Certificates: []tls.Certificate{cert}, - }, + Addr: addr, + TLSConfig: tlsConf, } errc := make(chan error, 1) go func() { errc <- s.ListenAndServeTLS("", "") }() @@ -2416,7 +2432,7 @@ func TestCloseNotifierPipelined(t *testing.T) { if err != nil { t.Fatalf("error dialing: %v", err) } - diec := make(chan bool, 2) + diec := make(chan bool, 1) go func() { const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n" _, err = io.WriteString(conn, req+req) // two requests @@ -2426,13 +2442,23 @@ func TestCloseNotifierPipelined(t *testing.T) { <-diec conn.Close() }() + reqs := 0 + closes := 0 For: for { select { case <-gotReq: - diec <- true + reqs++ + if reqs > 2 { + t.Fatal("too many requests") + } else if reqs > 1 { + diec <- true + } case <-sawClose: - break For + closes++ + if closes > 1 { + break For + } case <-time.After(5 * time.Second): ts.CloseClientConnections() t.Fatal("timeout") diff --git a/src/net/http/server.go b/src/net/http/server.go index 004a1f92fc..5e3b6084ae 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2233,10 +2233,11 @@ func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error { // Accepted connections are configured to enable TCP keep-alives. // // Filenames containing a certificate and matching private key for the -// server must be provided if the Server's TLSConfig.Certificates is -// not populated. If the certificate is signed by a certificate -// authority, the certFile should be the concatenation of the server's -// certificate, any intermediates, and the CA's certificate. +// server must be provided if neither the Server's TLSConfig.Certificates +// nor TLSConfig.GetCertificate are populated. If the certificate is +// signed by a certificate authority, the certFile should be the +// concatenation of the server's certificate, any intermediates, and +// the CA's certificate. // // If srv.Addr is blank, ":https" is used. // @@ -2258,7 +2259,8 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { config.NextProtos = append(config.NextProtos, "http/1.1") } - if len(config.Certificates) == 0 || certFile != "" || keyFile != "" { + configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil + if !configHasCert || certFile != "" || keyFile != "" { var err error config.Certificates = make([]tls.Certificate, 1) config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 41df906cf2..baf71d5e85 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -163,6 +163,22 @@ func (t *Transport) onceSetNextProtoDefaults() { return } if t.TLSNextProto != nil { + // This is the documented way to disable http2 on a + // Transport. + return + } + if t.TLSClientConfig != nil { + // Be conservative for now (for Go 1.6) at least and + // don't automatically enable http2 if they've + // specified a custom TLS config. Let them opt-in + // themselves via http2.ConfigureTransport so we don't + // surprise them by modifying their tls.Config. + // Issue 14275. + return + } + if t.ExpectContinueTimeout != 0 { + // Unsupported in http2, so disable http2 for now. + // Issue 13851. return } t2, err := http2configureTransport(t) diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 8cb89a4220..0c901b30a4 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -2885,23 +2885,34 @@ func TestTransportPrefersResponseOverWriteError(t *testing.T) { } func TestTransportAutomaticHTTP2(t *testing.T) { - tr := &Transport{} - _, err := tr.RoundTrip(new(Request)) - if err == nil { - t.Error("expected error from RoundTrip") - } - if tr.TLSNextProto["h2"] == nil { - t.Errorf("HTTP/2 not registered.") - } + testTransportAutoHTTP(t, &Transport{}, true) +} - // Now with TLSNextProto set: - tr = &Transport{TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper)} - _, err = tr.RoundTrip(new(Request)) +func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) { + testTransportAutoHTTP(t, &Transport{ + TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper), + }, false) +} + +func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) { + testTransportAutoHTTP(t, &Transport{ + TLSClientConfig: new(tls.Config), + }, false) +} + +func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) { + testTransportAutoHTTP(t, &Transport{ + ExpectContinueTimeout: 1 * time.Second, + }, false) +} + +func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) { + _, err := tr.RoundTrip(new(Request)) if err == nil { t.Error("expected error from RoundTrip") } - if tr.TLSNextProto["h2"] != nil { - t.Errorf("HTTP/2 registered, despite non-nil TLSNextProto field") + if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 { + t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2) } } diff --git a/src/net/net_windows_test.go b/src/net/net_windows_test.go index 095a339e02..df39032721 100644 --- a/src/net/net_windows_test.go +++ b/src/net/net_windows_test.go @@ -314,20 +314,43 @@ func TestInterfacesWithNetsh(t *testing.T) { } } -func netshInterfaceIPv4ShowAddress(name string) ([]string, error) { - out, err := runCmd("netsh", "interface", "ipv4", "show", "address", "name=\""+name+"\"") - if err != nil { - return nil, err - } +func netshInterfaceIPv4ShowAddress(name string, netshOutput []byte) []string { // adress information is listed like: + // + //Configuration for interface "Local Area Connection" + // DHCP enabled: Yes // IP Address: 10.0.0.2 // Subnet Prefix: 10.0.0.0/24 (mask 255.255.255.0) // IP Address: 10.0.0.3 // Subnet Prefix: 10.0.0.0/24 (mask 255.255.255.0) + // Default Gateway: 10.0.0.254 + // Gateway Metric: 0 + // InterfaceMetric: 10 + // + //Configuration for interface "Loopback Pseudo-Interface 1" + // DHCP enabled: No + // IP Address: 127.0.0.1 + // Subnet Prefix: 127.0.0.0/8 (mask 255.0.0.0) + // InterfaceMetric: 50 + // addrs := make([]string, 0) var addr, subnetprefix string - lines := bytes.Split(out, []byte{'\r', '\n'}) + var processingOurInterface bool + lines := bytes.Split(netshOutput, []byte{'\r', '\n'}) for _, line := range lines { + if !processingOurInterface { + if !bytes.HasPrefix(line, []byte("Configuration for interface")) { + continue + } + if !bytes.Contains(line, []byte(`"`+name+`"`)) { + continue + } + processingOurInterface = true + continue + } + if len(line) == 0 { + break + } if bytes.Contains(line, []byte("Subnet Prefix:")) { f := bytes.Split(line, []byte{':'}) if len(f) == 2 { @@ -351,18 +374,50 @@ func netshInterfaceIPv4ShowAddress(name string) ([]string, error) { } } } - return addrs, nil + return addrs } -func netshInterfaceIPv6ShowAddress(name string) ([]string, error) { +func netshInterfaceIPv6ShowAddress(name string, netshOutput []byte) []string { + // adress information is listed like: + // + //Address ::1 Parameters + //--------------------------------------------------------- + //Interface Luid : Loopback Pseudo-Interface 1 + //Scope Id : 0.0 + //Valid Lifetime : infinite + //Preferred Lifetime : infinite + //DAD State : Preferred + //Address Type : Other + //Skip as Source : false + // + //Address XXXX::XXXX:XXXX:XXXX:XXXX%11 Parameters + //--------------------------------------------------------- + //Interface Luid : Local Area Connection + //Scope Id : 0.11 + //Valid Lifetime : infinite + //Preferred Lifetime : infinite + //DAD State : Preferred + //Address Type : Other + //Skip as Source : false + // + // TODO: need to test ipv6 netmask too, but netsh does not outputs it - out, err := runCmd("netsh", "interface", "ipv6", "show", "address", "interface=\""+name+"\"") - if err != nil { - return nil, err - } + var addr string addrs := make([]string, 0) - lines := bytes.Split(out, []byte{'\r', '\n'}) + lines := bytes.Split(netshOutput, []byte{'\r', '\n'}) for _, line := range lines { + if addr != "" { + if len(line) == 0 { + addr = "" + continue + } + if string(line) != "Interface Luid : "+name { + continue + } + addrs = append(addrs, addr) + addr = "" + continue + } if !bytes.HasPrefix(line, []byte("Address")) { continue } @@ -383,9 +438,9 @@ func netshInterfaceIPv6ShowAddress(name string) ([]string, error) { f[0] = []byte(ParseIP(string(f[0])).String()) } - addrs = append(addrs, string(bytes.ToLower(bytes.TrimSpace(f[0])))) + addr = string(bytes.ToLower(bytes.TrimSpace(f[0]))) } - return addrs, nil + return addrs } func TestInterfaceAddrsWithNetsh(t *testing.T) { @@ -395,6 +450,16 @@ func TestInterfaceAddrsWithNetsh(t *testing.T) { if !isEnglishOS(t) { t.Skip("English version of OS required for this test") } + + outIPV4, err := runCmd("netsh", "interface", "ipv4", "show", "address") + if err != nil { + t.Fatal(err) + } + outIPV6, err := runCmd("netsh", "interface", "ipv6", "show", "address", "level=verbose") + if err != nil { + t.Fatal(err) + } + ift, err := Interfaces() if err != nil { t.Fatal(err) @@ -431,14 +496,8 @@ func TestInterfaceAddrsWithNetsh(t *testing.T) { } sort.Strings(have) - want, err := netshInterfaceIPv4ShowAddress(ifi.Name) - if err != nil { - t.Fatal(err) - } - wantIPv6, err := netshInterfaceIPv6ShowAddress(ifi.Name) - if err != nil { - t.Fatal(err) - } + want := netshInterfaceIPv4ShowAddress(ifi.Name, outIPV4) + wantIPv6 := netshInterfaceIPv6ShowAddress(ifi.Name, outIPV6) want = append(want, wantIPv6...) sort.Strings(want) @@ -487,8 +546,13 @@ func TestInterfaceHardwareAddrWithGetmac(t *testing.T) { // //Connection Name: Bluetooth Network Connection //Network Adapter: Bluetooth Device (Personal Area Network) - //Physical Address: XX-XX-XX-XX-XX-XX - //Transport Name: Media disconnected + //Physical Address: N/A + //Transport Name: Hardware not present + // + //Connection Name: VMware Network Adapter VMnet8 + //Network Adapter: VMware Virtual Ethernet Adapter for VMnet8 + //Physical Address: Disabled + //Transport Name: Disconnected // want := make(map[string]string) var name string @@ -516,6 +580,9 @@ func TestInterfaceHardwareAddrWithGetmac(t *testing.T) { if addr == "" { t.Fatal("empty address on \"Physical Address\" line: %q", line) } + if addr == "disabled" || addr == "n/a" { + continue + } addr = strings.Replace(addr, "-", ":", -1) want[name] = addr name = "" diff --git a/src/runtime/cgocheck.go b/src/runtime/cgocheck.go index 0077e22332..aebce1506d 100644 --- a/src/runtime/cgocheck.go +++ b/src/runtime/cgocheck.go @@ -135,9 +135,6 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) { hbits := heapBitsForAddr(uintptr(src)) for i := uintptr(0); i < off+size; i += sys.PtrSize { bits := hbits.bits() - if bits != 0 { - println(i, bits) - } if i >= off && bits&bitPointer != 0 { v := *(*unsafe.Pointer)(add(src, i)) if cgoIsGoPointer(v) { diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index b622eb4526..5f0e77b0dc 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -317,3 +317,22 @@ func TestNetpollDeadlock(t *testing.T) { t.Fatalf("output does not start with %q:\n%s", want, output) } } + +func TestPanicTraceback(t *testing.T) { + output := runTestProg(t, "testprog", "PanicTraceback") + want := "panic: hello" + if !strings.HasPrefix(output, want) { + t.Fatalf("output does not start with %q:\n%s", want, output) + } + + // Check functions in the traceback. + fns := []string{"panic", "main.pt1.func1", "panic", "main.pt2.func1", "panic", "main.pt2", "main.pt1"} + for _, fn := range fns { + re := regexp.MustCompile(`(?m)^` + regexp.QuoteMeta(fn) + `\(.*\n`) + idx := re.FindStringIndex(output) + if idx == nil { + t.Fatalf("expected %q function in traceback:\n%s", fn, output) + } + output = output[idx[1]:] + } +} diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 5284a37b0f..771b303f6e 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -14,6 +14,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "syscall" "testing" ) @@ -52,6 +53,18 @@ func TestCrashDumpsAllThreads(t *testing.T) { cmd = exec.Command(filepath.Join(dir, "a.exe")) cmd = testEnv(cmd) cmd.Env = append(cmd.Env, "GOTRACEBACK=crash") + + // Set GOGC=off. Because of golang.org/issue/10958, the tight + // loops in the test program are not preemptible. If GC kicks + // in, it may lock up and prevent main from saying it's ready. + newEnv := []string{} + for _, s := range cmd.Env { + if !strings.HasPrefix(s, "GOGC=") { + newEnv = append(newEnv, s) + } + } + cmd.Env = append(newEnv, "GOGC=off") + var outbuf bytes.Buffer cmd.Stdout = &outbuf cmd.Stderr = &outbuf @@ -137,8 +150,8 @@ func loop(i int, c chan bool) { func TestSignalExitStatus(t *testing.T) { testenv.MustHaveGoBuild(t) switch runtime.GOOS { - case "netbsd": - t.Skip("skipping on NetBSD; see https://golang.org/issue/14063") + case "netbsd", "solaris": + t.Skipf("skipping on %s; see https://golang.org/issue/14063", runtime.GOOS) } exe, err := buildTestProg(t, "testprog") if err != nil { diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go index c8b9746676..61d6ae4bf2 100644 --- a/src/runtime/export_linux_test.go +++ b/src/runtime/export_linux_test.go @@ -7,3 +7,4 @@ package runtime var NewOSProc0 = newosproc0 +var Mincore = mincore diff --git a/src/runtime/export_mmap_test.go b/src/runtime/export_mmap_test.go new file mode 100644 index 0000000000..11ea076f0b --- /dev/null +++ b/src/runtime/export_mmap_test.go @@ -0,0 +1,15 @@ +// Copyright 2016 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. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +// Export guts for testing. + +package runtime + +var Mmap = mmap + +const ENOMEM = _ENOMEM +const MAP_ANON = _MAP_ANON +const MAP_PRIVATE = _MAP_PRIVATE diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go index 1e388ec728..c3fe6106d7 100644 --- a/src/runtime/mem_bsd.go +++ b/src/runtime/mem_bsd.go @@ -59,9 +59,9 @@ func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer { return p } -func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) { - const _ENOMEM = 12 +const _ENOMEM = 12 +func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) { mSysStatInc(sysStat, n) // On 64-bit, we don't actually have v reserved, so tread carefully. diff --git a/src/runtime/os2_nacl.go b/src/runtime/os2_nacl.go index 0c91e0f737..d8c88db0ad 100644 --- a/src/runtime/os2_nacl.go +++ b/src/runtime/os2_nacl.go @@ -10,18 +10,19 @@ const ( // native_client/src/trusted/service_runtime/include/sys/errno.h // The errors are mainly copied from Linux. - _EPERM = 1 /* Operation not permitted */ - _ENOENT = 2 /* No such file or directory */ - _ESRCH = 3 /* No such process */ - _EINTR = 4 /* Interrupted system call */ - _EIO = 5 /* I/O error */ - _ENXIO = 6 /* No such device or address */ - _E2BIG = 7 /* Argument list too long */ - _ENOEXEC = 8 /* Exec format error */ - _EBADF = 9 /* Bad file number */ - _ECHILD = 10 /* No child processes */ - _EAGAIN = 11 /* Try again */ - _ENOMEM = 12 /* Out of memory */ + _EPERM = 1 /* Operation not permitted */ + _ENOENT = 2 /* No such file or directory */ + _ESRCH = 3 /* No such process */ + _EINTR = 4 /* Interrupted system call */ + _EIO = 5 /* I/O error */ + _ENXIO = 6 /* No such device or address */ + _E2BIG = 7 /* Argument list too long */ + _ENOEXEC = 8 /* Exec format error */ + _EBADF = 9 /* Bad file number */ + _ECHILD = 10 /* No child processes */ + _EAGAIN = 11 /* Try again */ + // _ENOMEM is defined in mem_bsd.go for nacl. + // _ENOMEM = 12 /* Out of memory */ _EACCES = 13 /* Permission denied */ _EFAULT = 14 /* Bad address */ _EBUSY = 16 /* Device or resource busy */ diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 7bda07bd4a..7ebb35c8e9 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -442,7 +442,21 @@ func madvise(addr unsafe.Pointer, n uintptr, flags int32) { //go:nosplit func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer { - return unsafe.Pointer(sysvicall6(&libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))) + p, err := doMmap(uintptr(addr), n, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off)) + if p == ^uintptr(0) { + return unsafe.Pointer(err) + } + return unsafe.Pointer(p) +} + +//go:nosplit +func doMmap(addr, n, prot, flags, fd, off uintptr) (uintptr, uintptr) { + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(&libc_mmap)) + libcall.n = 6 + libcall.args = uintptr(noescape(unsafe.Pointer(&addr))) + asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) + return libcall.r1, libcall.err } //go:nosplit diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index 7d677cb64e..e09a33d5d9 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -346,7 +346,7 @@ func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) { name := f.Name() // Hide runtime.goexit and any runtime functions at the beginning. // This is useful mainly for allocation traces. - wasPanic = name == "runtime.panic" + wasPanic = name == "runtime.gopanic" if name == "runtime.goexit" || !show && strings.HasPrefix(name, "runtime.") { continue } diff --git a/src/runtime/runtime-lldb_test.go b/src/runtime/runtime-lldb_test.go new file mode 100644 index 0000000000..2bd91c1ec0 --- /dev/null +++ b/src/runtime/runtime-lldb_test.go @@ -0,0 +1,262 @@ +// Copyright 2016 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 runtime_test + +import ( + "debug/elf" + "debug/macho" + "encoding/binary" + "internal/testenv" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" +) + +var lldbPath string + +func checkLldbPython(t *testing.T) { + cmd := exec.Command("lldb", "-P") + out, err := cmd.CombinedOutput() + if err != nil { + t.Skipf("skipping due to issue running lldb: %v\n%s", err, out) + } + lldbPath = strings.TrimSpace(string(out)) + + cmd = exec.Command("/usr/bin/python2.7", "-c", "import sys;sys.path.append(sys.argv[1]);import lldb; print('go lldb python support')", lldbPath) + out, err = cmd.CombinedOutput() + + if err != nil { + t.Skipf("skipping due to issue running python: %v\n%s", err, out) + } + if string(out) != "go lldb python support\n" { + t.Skipf("skipping due to lack of python lldb support: %s", out) + } + + if runtime.GOOS == "darwin" { + // Try to see if we have debugging permissions. + cmd = exec.Command("/usr/sbin/DevToolsSecurity", "-status") + out, err = cmd.CombinedOutput() + if err != nil { + t.Skipf("DevToolsSecurity failed: %v", err) + } else if !strings.Contains(string(out), "enabled") { + t.Skip(string(out)) + } + cmd = exec.Command("/usr/bin/groups") + out, err = cmd.CombinedOutput() + if err != nil { + t.Skipf("groups failed: %v", err) + } else if !strings.Contains(string(out), "_developer") { + t.Skip("Not in _developer group") + } + } +} + +const lldbHelloSource = ` +package main +import "fmt" +func main() { + mapvar := make(map[string]string,5) + mapvar["abc"] = "def" + mapvar["ghi"] = "jkl" + intvar := 42 + ptrvar := &intvar + fmt.Println("hi") // line 10 + _ = ptrvar +} +` + +const lldbScriptSource = ` +import sys +sys.path.append(sys.argv[1]) +import lldb +import os + +TIMEOUT_SECS = 5 + +debugger = lldb.SBDebugger.Create() +debugger.SetAsync(True) +target = debugger.CreateTargetWithFileAndArch("a.exe", None) +if target: + print "Created target" + main_bp = target.BreakpointCreateByLocation("main.go", 10) + if main_bp: + print "Created breakpoint" + process = target.LaunchSimple(None, None, os.getcwd()) + if process: + print "Process launched" + listener = debugger.GetListener() + process.broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) + while True: + event = lldb.SBEvent() + if listener.WaitForEvent(TIMEOUT_SECS, event): + if lldb.SBProcess.GetRestartedFromEvent(event): + continue + state = process.GetState() + if state in [lldb.eStateUnloaded, lldb.eStateLaunching, lldb.eStateRunning]: + continue + else: + print "Timeout launching" + break + if state == lldb.eStateStopped: + for t in process.threads: + if t.GetStopReason() == lldb.eStopReasonBreakpoint: + print "Hit breakpoint" + frame = t.GetFrameAtIndex(0) + if frame: + if frame.line_entry: + print "Stopped at %s:%d" % (frame.line_entry.file.basename, frame.line_entry.line) + if frame.function: + print "Stopped in %s" % (frame.function.name,) + var = frame.FindVariable('intvar') + if var: + print "intvar = %s" % (var.GetValue(),) + else: + print "no intvar" + else: + print "Process state", state + process.Destroy() +else: + print "Failed to create target a.exe" + +lldb.SBDebugger.Destroy(debugger) +sys.exit() +` + +const expectedLldbOutput = `Created target +Created breakpoint +Process launched +Hit breakpoint +Stopped at main.go:10 +Stopped in main.main +intvar = 42 +` + +func TestLldbPython(t *testing.T) { + testenv.MustHaveGoBuild(t) + if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final { + t.Skip("gdb test can fail with GOROOT_FINAL pending") + } + + checkLldbPython(t) + + dir, err := ioutil.TempDir("", "go-build") + if err != nil { + t.Fatalf("failed to create temp directory: %v", err) + } + defer os.RemoveAll(dir) + + src := filepath.Join(dir, "main.go") + err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644) + if err != nil { + t.Fatalf("failed to create file: %v", err) + } + + cmd := exec.Command("go", "build", "-gcflags", "-N -l", "-o", "a.exe") + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("building source %v\n%s", err, out) + } + + src = filepath.Join(dir, "script.py") + err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755) + if err != nil { + t.Fatalf("failed to create script: %v", err) + } + + cmd = exec.Command("/usr/bin/python2.7", "script.py", lldbPath) + cmd.Dir = dir + got, _ := cmd.CombinedOutput() + + if string(got) != expectedLldbOutput { + if strings.Contains(string(got), "Timeout launching") { + t.Skip("Timeout launching") + } + t.Fatalf("Unexpected lldb output:\n%s", got) + } +} + +// Check that aranges are valid even when lldb isn't installed. +func TestDwarfAranges(t *testing.T) { + testenv.MustHaveGoBuild(t) + dir, err := ioutil.TempDir("", "go-build") + if err != nil { + t.Fatalf("failed to create temp directory: %v", err) + } + defer os.RemoveAll(dir) + + src := filepath.Join(dir, "main.go") + err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644) + if err != nil { + t.Fatalf("failed to create file: %v", err) + } + + cmd := exec.Command("go", "build", "-o", "a.exe") + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("building source %v\n%s", err, out) + } + + filename := filepath.Join(dir, "a.exe") + if f, err := elf.Open(filename); err == nil { + sect := f.Section(".debug_aranges") + if sect == nil { + t.Fatal("Missing aranges section") + } + verifyAranges(t, f.ByteOrder, sect.Open()) + } else if f, err := macho.Open(filename); err == nil { + sect := f.Section("__debug_aranges") + if sect == nil { + t.Fatal("Missing aranges section") + } + verifyAranges(t, f.ByteOrder, sect.Open()) + } else { + t.Skip("Not an elf or macho binary.") + } +} + +func verifyAranges(t *testing.T, byteorder binary.ByteOrder, data io.ReadSeeker) { + var header struct { + UnitLength uint32 // does not include the UnitLength field + Version uint16 + Offset uint32 + AddressSize uint8 + SegmentSize uint8 + } + for { + offset, err := data.Seek(0, 1) + if err != nil { + t.Fatalf("Seek error: %v", err) + } + if err = binary.Read(data, byteorder, &header); err == io.EOF { + return + } else if err != nil { + t.Fatalf("Error reading arange header: %v", err) + } + tupleSize := int64(header.SegmentSize) + 2*int64(header.AddressSize) + lastTupleOffset := offset + int64(header.UnitLength) + 4 - tupleSize + if lastTupleOffset%tupleSize != 0 { + t.Fatalf("Invalid arange length %d, (addr %d, seg %d)", header.UnitLength, header.AddressSize, header.SegmentSize) + } + if _, err = data.Seek(lastTupleOffset, 0); err != nil { + t.Fatalf("Seek error: %v", err) + } + buf := make([]byte, tupleSize) + if n, err := data.Read(buf); err != nil || int64(n) < tupleSize { + t.Fatalf("Read error: %v", err) + } + for _, val := range buf { + if val != 0 { + t.Fatalf("Invalid terminator") + } + } + } +} diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go index 5344ed2051..58c797f1dd 100644 --- a/src/runtime/runtime_linux_test.go +++ b/src/runtime/runtime_linux_test.go @@ -8,6 +8,7 @@ import ( . "runtime" "syscall" "testing" + "unsafe" ) var pid, tid int @@ -27,3 +28,15 @@ func TestLockOSThread(t *testing.T) { t.Fatalf("pid=%d but tid=%d", pid, tid) } } + +// Test that error values are negative. Use address 1 (a misaligned +// pointer) to get -EINVAL. +func TestMincoreErrorSign(t *testing.T) { + var dst byte + v := Mincore(unsafe.Pointer(uintptr(1)), 1, &dst) + + const EINVAL = 0x16 + if v != -EINVAL { + t.Errorf("mincore = %v, want %v", v, -EINVAL) + } +} diff --git a/src/runtime/runtime_mmap_test.go b/src/runtime/runtime_mmap_test.go new file mode 100644 index 0000000000..ff5e733cb0 --- /dev/null +++ b/src/runtime/runtime_mmap_test.go @@ -0,0 +1,30 @@ +// Copyright 2016 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. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package runtime_test + +import ( + "runtime" + "runtime/internal/sys" + "testing" +) + +// Test that the error value returned by mmap is positive, as that is +// what the code in mem_bsd.go, mem_darwin.go, and mem_linux.go expects. +// See the uses of ENOMEM in sysMap in those files. +func TestMmapErrorSign(t *testing.T) { + p := runtime.Mmap(nil, ^uintptr(0)&^(sys.PhysPageSize-1), 0, runtime.MAP_ANON|runtime.MAP_PRIVATE, -1, 0) + + // The runtime.mmap function is nosplit, but t.Errorf is not. + // Reset the pointer so that we don't get an "invalid stack + // pointer" error from t.Errorf if we call it. + v := uintptr(p) + p = nil + + if v != runtime.ENOMEM { + t.Errorf("mmap = %v, want %v", v, runtime.ENOMEM) + } +} diff --git a/src/runtime/stack_test.go b/src/runtime/stack_test.go index fa073f19ad..928d1eca20 100644 --- a/src/runtime/stack_test.go +++ b/src/runtime/stack_test.go @@ -111,7 +111,8 @@ func TestStackGrowth(t *testing.T) { select { case <-done: case <-time.After(20 * time.Second): - t.Fatal("finalizer did not run") + t.Error("finalizer did not run") + return } }() wg.Wait() @@ -191,7 +192,6 @@ func TestStackGrowthCallback(t *testing.T) { <-done }) }() - wg.Wait() } diff --git a/src/runtime/string.go b/src/runtime/string.go index f8ccd41b1d..dd04bda04b 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -139,7 +139,7 @@ func slicebytetostringtmp(b []byte) string { func stringtoslicebyte(buf *tmpBuf, s string) []byte { var b []byte if buf != nil && len(s) <= len(buf) { - b = buf[:len(s)] + b = buf[:len(s):len(s)] } else { b = rawbyteslice(len(s)) } @@ -171,7 +171,7 @@ func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune { } var a []rune if buf != nil && n <= len(buf) { - a = buf[:n] + a = buf[:n:n] } else { a = rawruneslice(n) } diff --git a/src/runtime/string_test.go b/src/runtime/string_test.go index 318a5532e5..150a25520a 100644 --- a/src/runtime/string_test.go +++ b/src/runtime/string_test.go @@ -222,3 +222,18 @@ func TestRangeStringCast(t *testing.T) { t.Fatalf("want 0 allocs, got %v", n) } } + +func TestString2Slice(t *testing.T) { + // Make sure we don't return slices that expose + // an unzeroed section of stack-allocated temp buf + // between len and cap. See issue 14232. + s := "foož" + b := ([]byte)(s) + if cap(b) != 5 { + t.Errorf("want cap of 5, got %d", cap(b)) + } + r := ([]rune)(s) + if cap(r) != 4 { + t.Errorf("want cap of 4, got %d", cap(r)) + } +} diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s index ca0e07aaa4..94c101a3d4 100644 --- a/src/runtime/sys_linux_arm64.s +++ b/src/runtime/sys_linux_arm64.s @@ -269,6 +269,9 @@ TEXT runtime·mmap(SB),NOSPLIT,$-8 MOVD $SYS_mmap, R8 SVC + CMN $4095, R0 + BCC 2(PC) + NEG R0,R0 MOVD R0, ret+32(FP) RET diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index 6ccb38f90b..26437ddde4 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -168,6 +168,7 @@ TEXT runtime·mincore(SB),NOSPLIT,$-8-28 MOVV dst+16(FP), R6 MOVV $SYS_mincore, R2 SYSCALL + SUBVU R2, R0, R2 // caller expects negative errno MOVW R2, ret+24(FP) RET diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index ba410c51b6..d063e025a6 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -153,6 +153,7 @@ TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 MOVD n+8(FP), R4 MOVD dst+16(FP), R5 SYSCALL $SYS_mincore + NEG R3 // caller expects negative errno MOVW R3, ret+24(FP) RET diff --git a/src/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s index bf2d36ec85..e69a0b7bfe 100644 --- a/src/runtime/sys_nacl_386.s +++ b/src/runtime/sys_nacl_386.s @@ -227,6 +227,9 @@ TEXT runtime·mmap(SB),NOSPLIT,$32 LEAL 24(SP), AX MOVL AX, 20(SP) NACL_SYSCALL(SYS_mmap) + CMPL AX, $-4095 + JNA 2(PC) + NEGL AX MOVL AX, ret+24(FP) RET diff --git a/src/runtime/testdata/testprog/deadlock.go b/src/runtime/testdata/testprog/deadlock.go index 7f0a0cd1e0..73fbf6224d 100644 --- a/src/runtime/testdata/testprog/deadlock.go +++ b/src/runtime/testdata/testprog/deadlock.go @@ -29,7 +29,7 @@ func init() { register("GoexitInPanic", GoexitInPanic) register("PanicAfterGoexit", PanicAfterGoexit) register("RecoveredPanicAfterGoexit", RecoveredPanicAfterGoexit) - + register("PanicTraceback", PanicTraceback) } func SimpleDeadlock() { @@ -171,3 +171,21 @@ func RecoveredPanicAfterGoexit() { }() runtime.Goexit() } + +func PanicTraceback() { + pt1() +} + +func pt1() { + defer func() { + panic("panic pt1") + }() + pt2() +} + +func pt2() { + defer func() { + panic("panic pt2") + }() + panic("hello") +} diff --git a/src/runtime/time.go b/src/runtime/time.go index ffe7590526..3f8f6968c2 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -16,7 +16,7 @@ type timer struct { i int // heap index // Timer wakes up at when, and then at when+period, ... (period > 0 only) - // each time calling f(now, arg) in the timer goroutine, so f must be + // each time calling f(arg, now) in the timer goroutine, so f must be // a well-behaved function and not block. when int64 period int64 diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 6559cd7ba3..b4bfe71627 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -380,7 +380,11 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic { tracepc-- } - print(funcname(f), "(") + name := funcname(f) + if name == "runtime.gopanic" { + name = "panic" + } + print(name, "(") argp := (*[100]uintptr)(unsafe.Pointer(frame.argp)) for i := uintptr(0); i < frame.arglen/sys.PtrSize; i++ { if i >= 10 { @@ -617,10 +621,10 @@ func showframe(f *_func, gp *g) bool { level, _, _ := gotraceback() name := funcname(f) - // Special case: always show runtime.panic frame, so that we can + // Special case: always show runtime.gopanic frame, so that we can // see where a panic started in the middle of a stack trace. // See golang.org/issue/5832. - if name == "runtime.panic" { + if name == "runtime.gopanic" { return true } diff --git a/test/fixedbugs/issue14331.dir/a.go b/test/fixedbugs/issue14331.dir/a.go new file mode 100644 index 0000000000..1b7f853bc9 --- /dev/null +++ b/test/fixedbugs/issue14331.dir/a.go @@ -0,0 +1,14 @@ +// Copyright 2016 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 a + +var S struct { + Str string `tag` +} + +func F() string { + v := S + return v.Str +} diff --git a/test/fixedbugs/issue14331.dir/b.go b/test/fixedbugs/issue14331.dir/b.go new file mode 100644 index 0000000000..7a0abb2506 --- /dev/null +++ b/test/fixedbugs/issue14331.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2016 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 b + +import "./a" + +func G() string { + return a.F() +} diff --git a/test/fixedbugs/issue14331.go b/test/fixedbugs/issue14331.go new file mode 100644 index 0000000000..32f3e5156c --- /dev/null +++ b/test/fixedbugs/issue14331.go @@ -0,0 +1,9 @@ +// compiledir + +// Copyright 2016 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. + +// Inline function misses struct tags. + +package ignored diff --git a/test/writebarrier.go b/test/writebarrier.go index 9b741a60df..dcd20a0225 100644 --- a/test/writebarrier.go +++ b/test/writebarrier.go @@ -144,3 +144,17 @@ type T8 struct { func f16(x []T8, y T8) []T8 { return append(x, y) // ERROR "write barrier" } + +func t1(i interface{}) **int { + // From issue 14306, make sure we have write barriers in a type switch + // where the assigned variable escapes. + switch x := i.(type) { // ERROR "write barrier" + case *int: + return &x + } + switch y := i.(type) { // no write barrier here + case **int: + return y + } + return nil +} |