I have committed a patch to libgo to update to the go1.8rc2 release candidate.

This uncovered a bug in the calculation of the hash code for
reflect.FuncOf, which is fixed by this patch.

I noticed while doing the merge that somewhere along the way a bunch
of testdata files were dropped.  I added them here, although they are
not new in 1.8rc2.

The new testdata files are largely uninteresting, so in this e-mail
message I've only included the changes to non-test files.

Committed to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 244824)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -1,4 +1,4 @@
-0655e25d8e4acfac50c6b1422dc32eca3e30803a
+fb609ff6d940768cf4db4ab7deb93b2ab686e45d
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/MERGE
===================================================================
--- libgo/MERGE (revision 244456)
+++ libgo/MERGE (working copy)
@@ -1,4 +1,4 @@
-3de6e96e4b8147f5267a2e8218a7c780b09a434f
+59f181b6fda68ece22882945853ca2df9dbf1c88
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
Index: libgo/VERSION
===================================================================
--- libgo/VERSION       (revision 244456)
+++ libgo/VERSION       (working copy)
@@ -1 +1 @@
-go1.8rc1
+go1.8rc2
Index: libgo/go/cmd/go/bug.go
===================================================================
--- libgo/go/cmd/go/bug.go      (revision 244456)
+++ libgo/go/cmd/go/bug.go      (working copy)
@@ -20,11 +20,10 @@ import (
 var cmdBug = &Command{
        Run:       runBug,
        UsageLine: "bug",
-       Short:     "print information for bug reports",
+       Short:     "start a bug report",
        Long: `
-Bug prints information that helps file effective bug reports.
-
-Bugs may be reported at https://golang.org/issue/new.
+Bug opens the default browser and starts a new bug report.
+The report includes useful system information.
        `,
 }
 
Index: libgo/go/cmd/go/test.go
===================================================================
--- libgo/go/cmd/go/test.go     (revision 244456)
+++ libgo/go/cmd/go/test.go     (working copy)
@@ -906,9 +906,13 @@ func (b *builder) test(p *Package) (buil
 
        if buildContext.GOOS == "darwin" {
                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 {
                if len(cp.coverVars) > 0 {
@@ -1355,7 +1359,8 @@ type testFuncs struct {
        NeedTest    bool
        ImportXtest bool
        NeedXtest   bool
-       NeedCgo     bool
+       NeedOS      bool
+       IsIOS       bool
        Cover       []coverInfo
 }
 
@@ -1456,7 +1461,7 @@ var testmainTmpl = template.Must(templat
 package main
 
 import (
-{{if not .TestMain}}
+{{if .NeedOS}}
        "os"
 {{end}}
        "testing"
@@ -1472,8 +1477,10 @@ import (
        _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
 {{end}}
 
-{{if .NeedCgo}}
+{{if .IsIOS}}
+       "os/signal"
        _ "runtime/cgo"
+       "syscall"
 {{end}}
 )
 
@@ -1535,6 +1542,32 @@ func coverRegisterFile(fileName string,
 {{end}}
 
 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}}
        testing.RegisterCover(testing.Cover{
                Mode: {{printf "%q" .CoverMode}},
Index: libgo/go/compress/bzip2/bzip2_test.go
===================================================================
--- libgo/go/compress/bzip2/bzip2_test.go       (revision 244166)
+++ libgo/go/compress/bzip2/bzip2_test.go       (working copy)
@@ -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) {
        // Determine the uncompressed size of testfile.
        uncompressedSize, err := io.Copy(ioutil.Discard, 
NewReader(bytes.NewReader(compressed)))
@@ -227,6 +221,18 @@ func benchmarkDecode(b *testing.B, compr
        }
 }
 
-func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
-func BenchmarkDecodeTwain(b *testing.B)  { benchmarkDecode(b, twain) }
-func BenchmarkDecodeRand(b *testing.B)   { benchmarkDecode(b, random) }
+func BenchmarkDecodeDigits(b *testing.B) {
+       digits := mustLoadFile("testdata/e.txt.bz2")
+       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)
+}
Index: libgo/go/compress/flate/deflate.go
===================================================================
--- libgo/go/compress/flate/deflate.go  (revision 244456)
+++ libgo/go/compress/flate/deflate.go  (working copy)
@@ -136,14 +136,17 @@ func (d *compressor) fillDeflate(b []byt
                        delta := d.hashOffset - 1
                        d.hashOffset -= 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 {
                                        d.hashPrev[i] = uint32(int(v) - delta)
                                } else {
                                        d.hashPrev[i] = 0
                                }
                        }
-                       for i, v := range d.hashHead {
+                       for i, v := range d.hashHead[:] {
                                if int(v) > delta {
                                        d.hashHead[i] = uint32(int(v) - delta)
                                } else {
Index: libgo/go/compress/flate/deflate_test.go
===================================================================
--- libgo/go/compress/flate/deflate_test.go     (revision 244456)
+++ libgo/go/compress/flate/deflate_test.go     (working copy)
@@ -12,6 +12,7 @@ import (
        "io"
        "io/ioutil"
        "reflect"
+       "runtime/debug"
        "sync"
        "testing"
 )
@@ -864,3 +865,33 @@ func TestBestSpeedMaxMatchOffset(t *test
                }
        }
 }
+
+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)
+       }
+}
Index: libgo/go/compress/flate/deflatefast.go
===================================================================
--- libgo/go/compress/flate/deflatefast.go      (revision 244456)
+++ libgo/go/compress/flate/deflatefast.go      (working copy)
@@ -60,7 +60,7 @@ func newDeflateFast() *deflateFast {
 func (e *deflateFast) encode(dst []token, src []byte) []token {
        // Ensure that e.cur doesn't wrap.
        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
@@ -265,6 +265,21 @@ func (e *deflateFast) reset() {
 
        // Protect against e.cur wraparound.
        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{}
        }
 }
Index: libgo/go/compress/gzip/issue14937_test.go
===================================================================
--- libgo/go/compress/gzip/issue14937_test.go   (revision 244456)
+++ libgo/go/compress/gzip/issue14937_test.go   (working copy)
@@ -9,11 +9,17 @@ import (
        "testing"
 )
 
-// Per golang.org/issue/14937, check that every .gz file
-// in the tree has a zero mtime.
+// TestGZIPFilesHaveZeroMTimes checks that every .gz file in the tree
+// 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) {
-       if testing.Short() && testenv.Builder() == "" {
-               t.Skip("skipping in short mode")
+       // To avoid spurious false positives due to untracked GZIP files that
+       // 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())
        if err != nil {
Index: libgo/go/crypto/tls/cipher_suites.go
===================================================================
--- libgo/go/crypto/tls/cipher_suites.go        (revision 244456)
+++ libgo/go/crypto/tls/cipher_suites.go        (working copy)
@@ -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_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_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_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_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_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_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_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},
Index: libgo/go/crypto/tls/tls.go
===================================================================
--- libgo/go/crypto/tls/tls.go  (revision 244456)
+++ libgo/go/crypto/tls/tls.go  (working copy)
@@ -6,8 +6,8 @@
 package tls
 
 // BUG(agl): The crypto/tls package only implements some countermeasures
-// against Lucky13 attacks on CBC-mode encryption. See
-// http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
+// against Lucky13 attacks on CBC-mode encryption, and only on SHA1
+// variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
 // https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
 
 import (
Index: libgo/go/crypto/x509/cert_pool.go
===================================================================
--- libgo/go/crypto/x509/cert_pool.go   (revision 244456)
+++ libgo/go/crypto/x509/cert_pool.go   (working copy)
@@ -4,7 +4,11 @@
 
 package x509
 
-import "encoding/pem"
+import (
+       "encoding/pem"
+       "errors"
+       "runtime"
+)
 
 // CertPool is a set of certificates.
 type CertPool struct {
@@ -26,6 +30,11 @@ func NewCertPool() *CertPool {
 // Any mutations to the returned pool are not written to disk and do
 // not affect any other pool.
 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()
 }
 
Index: libgo/go/crypto/x509/root_windows.go
===================================================================
--- libgo/go/crypto/x509/root_windows.go        (revision 244456)
+++ libgo/go/crypto/x509/root_windows.go        (working copy)
@@ -226,6 +226,11 @@ func (c *Certificate) systemVerify(opts
 }
 
 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
 
        store, err := syscall.CertOpenSystemStore(0, 
syscall.StringToUTF16Ptr("ROOT"))
Index: libgo/go/crypto/x509/x509_test.go
===================================================================
--- libgo/go/crypto/x509/x509_test.go   (revision 244456)
+++ libgo/go/crypto/x509/x509_test.go   (working copy)
@@ -24,6 +24,7 @@ import (
        "net"
        "os/exec"
        "reflect"
+       "runtime"
        "strings"
        "testing"
        "time"
@@ -1477,6 +1478,9 @@ func TestMultipleRDN(t *testing.T) {
 }
 
 func TestSystemCertPool(t *testing.T) {
+       if runtime.GOOS == "windows" {
+               t.Skip("not implemented on Windows; Issue 16736, 18609")
+       }
        _, err := SystemCertPool()
        if err != nil {
                t.Fatal(err)
Index: libgo/go/go/ast/scope.go
===================================================================
--- libgo/go/go/ast/scope.go    (revision 244166)
+++ libgo/go/go/ast/scope.go    (working copy)
@@ -70,10 +70,8 @@ func (s *Scope) String() string {
 // The Data fields contains object-specific data:
 //
 //     Kind    Data type         Data value
-//     Pkg     *types.Package    package scope
+//     Pkg     *Scope            package scope
 //     Con     int               iota for the respective declaration
-//     Con     != nil            constant value
-//     Typ     *Scope            (used as method scope during type checking - 
transient)
 //
 type Object struct {
        Kind ObjKind
Index: libgo/go/go/doc/doc_test.go
===================================================================
--- libgo/go/go/doc/doc_test.go (revision 244166)
+++ libgo/go/go/doc/doc_test.go (working copy)
@@ -25,7 +25,7 @@ var files = flag.String("files", "", "co
 
 const dataDir = "testdata"
 
-var templateTxt = readTemplate("template.txt")
+var templateTxt *template.Template
 
 func readTemplate(filename string) *template.Template {
        t := template.New(filename)
@@ -96,6 +96,9 @@ func test(t *testing.T, mode Mode) {
        if err != nil {
                t.Fatal(err)
        }
+       if templateTxt == nil {
+               templateTxt = readTemplate("template.txt")
+       }
 
        // test packages
        for _, pkg := range pkgs {
Index: libgo/go/go/parser/performance_test.go
===================================================================
--- libgo/go/go/parser/performance_test.go      (revision 244166)
+++ libgo/go/go/parser/performance_test.go      (working copy)
@@ -10,17 +10,12 @@ import (
        "testing"
 )
 
-var src = readFile("parser.go")
-
-func readFile(filename string) []byte {
-       data, err := ioutil.ReadFile(filename)
+func BenchmarkParse(b *testing.B) {
+       src, err := ioutil.ReadFile("parser.go")
        if err != nil {
-               panic(err)
+               b.Fatal(err)
        }
-       return data
-}
-
-func BenchmarkParse(b *testing.B) {
+       b.ResetTimer()
        b.SetBytes(int64(len(src)))
        for i := 0; i < b.N; i++ {
                if _, err := ParseFile(token.NewFileSet(), "", src, 
ParseComments); err != nil {
Index: libgo/go/net/http/serve_test.go
===================================================================
--- libgo/go/net/http/serve_test.go     (revision 244456)
+++ libgo/go/net/http/serve_test.go     (working copy)
@@ -5173,3 +5173,142 @@ func TestServerDuplicateBackgroundRead(t
        }
        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")
+       }
+}
Index: libgo/go/net/http/server.go
===================================================================
--- libgo/go/net/http/server.go (revision 244456)
+++ libgo/go/net/http/server.go (working copy)
@@ -164,7 +164,7 @@ type Flusher interface {
 // should always test for this ability at runtime.
 type Hijacker interface {
        // 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.
        //
        // It becomes the caller's responsibility to manage
@@ -174,6 +174,9 @@ type Hijacker interface {
        // already set, depending on the configuration of the
        // Server. It is the caller's responsibility to set
        // or clear those deadlines as needed.
+       //
+       // The returned bufio.Reader may contain unprocessed buffered
+       // data from the client.
        Hijack() (net.Conn, *bufio.ReadWriter, error)
 }
 
@@ -293,6 +296,11 @@ func (c *conn) hijackLocked() (rwc net.C
        rwc.SetDeadline(time.Time{})
 
        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)
        return
 }
Index: libgo/go/net/http/transport_test.go
===================================================================
--- libgo/go/net/http/transport_test.go (revision 244456)
+++ libgo/go/net/http/transport_test.go (working copy)
@@ -36,6 +36,7 @@ import (
        "strconv"
        "strings"
        "sync"
+       "sync/atomic"
        "testing"
        "time"
 )
@@ -2545,6 +2546,13 @@ type closerFunc func() error
 
 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
 // 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
@@ -2557,66 +2565,78 @@ func (f closerFunc) Close() error { retu
 func TestRetryIdempotentRequestsOnError(t *testing.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) 
{
+               logf("Handler")
+               w.Header().Set("X-Status", "ok")
        }))
        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}
 
-       const N = 2
-       retryc := make(chan struct{}, N)
        SetRoundTripRetried(func() {
-               retryc <- struct{}{}
+               logf("Retried.")
        })
        defer SetRoundTripRetried(nil)
 
-       for n := 0; n < 100; n++ {
-               // open 2 conns
-               errc := make(chan error, N)
-               for i := 0; i < N; i++ {
-                       // 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
-                       }()
+       for i := 0; i < 3; i++ {
+               res, err := c.Get("http://fake.golang/";)
+               if err != nil {
+                       t.Fatalf("i=%d: Get = %v", i, err)
                }
+               res.Body.Close()
+       }
 
-               for i := 0; i < N; i++ {
-                       if err := <-errc; err != nil {
-                               t.Fatal(err)
-                       }
-               }
-               for i := 0; i < N; i++ {
-                       select {
-                       case <-retryc:
-                               // we triggered a retry, test was successful
-                               t.Logf("finished after %d runs\n", n)
-                               return
-                       default:
-                       }
-               }
+       mu.Lock()
+       got := logbuf.String()
+       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")
+Handler
+intentional write failure
+Retried.
+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")
+Handler
+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
Index: libgo/go/os/os_test.go
===================================================================
--- libgo/go/os/os_test.go      (revision 244456)
+++ libgo/go/os/os_test.go      (working copy)
@@ -52,12 +52,15 @@ var sysdir = func() *sysDir {
        case "darwin":
                switch runtime.GOARCH {
                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()
                        if err != nil {
                                wd = err.Error()
                        }
                        return &sysDir{
-                               filepath.Join(wd, "..", ".."),
+                               wd,
                                []string{
                                        "ResourceRules.plist",
                                        "Info.plist",
Index: libgo/go/reflect/all_test.go
===================================================================
--- libgo/go/reflect/all_test.go        (revision 244456)
+++ libgo/go/reflect/all_test.go        (working copy)
@@ -26,6 +26,8 @@ import (
        "unsafe"
 )
 
+var sink interface{}
+
 func TestBool(t *testing.T) {
        v := ValueOf(true)
        if v.Bool() != true {
@@ -5348,6 +5350,72 @@ func TestCallGC(t *testing.T) {
        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 {
        rcvr, t                  Type
        size, argsize, retOffset uintptr
Index: libgo/go/reflect/type.go
===================================================================
--- libgo/go/reflect/type.go    (revision 244456)
+++ libgo/go/reflect/type.go    (working copy)
@@ -1677,7 +1677,7 @@ func FuncOf(in, out []Type, variadic boo
        *ft = *prototype
 
        // Build a hash and minimally populate ft.
-       var hash uint32 = 8
+       var hash uint32
        var fin, fout []*rtype
        shift := uint(1)
        for _, in := range in {
@@ -1697,6 +1697,7 @@ func FuncOf(in, out []Type, variadic boo
                hash++
        }
        hash <<= 4
+       hash += 8
        ft.hash = hash
        ft.in = fin
        ft.out = fout
Index: libgo/go/testing/benchmark.go
===================================================================
--- libgo/go/testing/benchmark.go       (revision 244456)
+++ libgo/go/testing/benchmark.go       (working copy)
@@ -219,7 +219,7 @@ func (b *B) run1() bool {
        }
        // Only print the output if we know we are not going to proceed.
        // Otherwise it is printed in processBench.
-       if b.hasSub || b.finished {
+       if atomic.LoadInt32(&b.hasSub) != 0 || b.finished {
                tag := "BENCH"
                if b.skipped {
                        tag = "SKIP"
@@ -460,10 +460,13 @@ func (ctx *benchContext) processBench(b
 //
 // 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.
+//
+// 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 {
        // 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.
-       b.hasSub = true
+       atomic.StoreInt32(&b.hasSub, 1)
        benchmarkLock.Unlock()
        defer benchmarkLock.Lock()
 
Index: libgo/go/testing/sub_test.go
===================================================================
--- libgo/go/testing/sub_test.go        (revision 244456)
+++ libgo/go/testing/sub_test.go        (working copy)
@@ -6,6 +6,7 @@ package testing
 
 import (
        "bytes"
+       "fmt"
        "regexp"
        "strings"
        "sync/atomic"
@@ -515,3 +516,19 @@ func TestBenchmarkOutput(t *T) {
        Benchmark(func(b *B) { b.Error("do not print this output") })
        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
+       }
+}
Index: libgo/go/testing/testing.go
===================================================================
--- libgo/go/testing/testing.go (revision 244456)
+++ libgo/go/testing/testing.go (working copy)
@@ -216,6 +216,7 @@ import (
        "strconv"
        "strings"
        "sync"
+       "sync/atomic"
        "time"
 )
 
@@ -267,8 +268,8 @@ type common struct {
        skipped    bool         // Test of benchmark has been skipped.
        finished   bool         // Test function has completed.
        done       bool         // Test is finished and all subtests have 
completed.
-       hasSub     bool
-       raceErrors int // number of races detected during test
+       hasSub     int32        // written atomically
+       raceErrors int          // number of races detected during test
 
        parent   *common
        level    int       // Nesting depth of test or benchmark.
@@ -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
                // the user does not appropriately synchronizes a goroutine.
                t.done = true
-               if t.parent != nil && !t.hasSub {
+               if t.parent != nil && atomic.LoadInt32(&t.hasSub) == 0 {
                        t.setRan()
                }
                t.signal <- true
@@ -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 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 {
-       t.hasSub = true
+       atomic.StoreInt32(&t.hasSub, 1)
        testName, ok := t.context.match.fullName(&t.common, name)
        if !ok {
                return true
Index: libgo/merge.sh
===================================================================
--- libgo/merge.sh      (revision 244456)
+++ libgo/merge.sh      (working copy)
@@ -147,7 +147,7 @@ done
 
 (cd ${NEWDIR}/src && find . -name testdata -print) | while read d; do
   skip=false
-  case "$f" in
+  case "$d" in
   ./cmd/cgo/* | ./cmd/go/* | ./cmd/gofmt/* | ./cmd/internal/browser/*)
     ;;
   ./cmd/*)

Reply via email to