Commit 6b86b09a authored by Filippo Valsorda's avatar Filippo Valsorda

[dev.boringcrypto.go1.12] all: merge go1.12.6 into dev.boringcrypto.go1.12

Change-Id: I2598fb7f3a350e0244527c5244e423f9a9e01b86
parents ad495d31 4ce6a8e8
...@@ -69,6 +69,14 @@ the go command, the runtime, and the <code>os</code> package. See the ...@@ -69,6 +69,14 @@ the go command, the runtime, and the <code>os</code> package. See the
1.12.5 milestone</a> on our issue tracker for details. 1.12.5 milestone</a> on our issue tracker for details.
</p> </p>
<p>
go1.12.6 (released 2019/06/11) includes fixes to the compiler, the linker,
the go command, and the <code>crypto/x509</code>, <code>net/http</code>, and
<code>os</code> packages. See the
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.6">Go
1.12.6 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2> <h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
<p> <p>
...@@ -154,6 +162,12 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.10">Go ...@@ -154,6 +162,12 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.10">Go
1.11.10 milestone</a> on our issue tracker for details. 1.11.10 milestone</a> on our issue tracker for details.
</p> </p>
<p>
go1.11.11 (released 2019/06/11) includes a fix to the <code>crypto/x509</code> package.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.11">Go
1.11.11 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2> <h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
<p> <p>
......
...@@ -555,6 +555,13 @@ const ( ...@@ -555,6 +555,13 @@ const (
inNonInitFunction inNonInitFunction
) )
func (c initContext) String() string {
if c == inInitFunction {
return "inInitFunction"
}
return "inNonInitFunction"
}
// from here down is the walk analysis // from here down is the walk analysis
// of composite literals. // of composite literals.
// most of the work is to generate // most of the work is to generate
...@@ -913,7 +920,13 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { ...@@ -913,7 +920,13 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
break break
case OARRAYLIT, OSTRUCTLIT: case OARRAYLIT, OSTRUCTLIT:
fixedlit(ctxt, initKindDynamic, value, a, init) k := initKindDynamic
if vstat == nil {
// Generate both static and dynamic initializations.
// See issue #31987.
k = initKindLocalCode
}
fixedlit(ctxt, k, value, a, init)
continue continue
} }
......
...@@ -321,9 +321,10 @@ Search: ...@@ -321,9 +321,10 @@ Search:
// preal, packages that import the package under test should get ptest instead // preal, packages that import the package under test should get ptest instead
// of preal. This is particularly important if pxtest depends on functionality // of preal. This is particularly important if pxtest depends on functionality
// exposed in test sources in ptest. Second, if there is a main package // exposed in test sources in ptest. Second, if there is a main package
// (other than pmain) anywhere, we need to clear p.Internal.BuildInfo in // (other than pmain) anywhere, we need to set p.Internal.ForceLibrary and
// the test copy to prevent link conflicts. This may happen if both -coverpkg // clear p.Internal.BuildInfo in the test copy to prevent link conflicts.
// and the command line patterns include multiple main packages. // This may happen if both -coverpkg and the command line patterns include
// multiple main packages.
func recompileForTest(pmain, preal, ptest, pxtest *Package) { func recompileForTest(pmain, preal, ptest, pxtest *Package) {
// The "test copy" of preal is ptest. // The "test copy" of preal is ptest.
// For each package that depends on preal, make a "test copy" // For each package that depends on preal, make a "test copy"
...@@ -354,6 +355,7 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) { ...@@ -354,6 +355,7 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) {
p = p1 p = p1
p.Target = "" p.Target = ""
p.Internal.BuildInfo = "" p.Internal.BuildInfo = ""
p.Internal.ForceLibrary = true
} }
// Update p.Internal.Imports to use test copies. // Update p.Internal.Imports to use test copies.
......
...@@ -177,6 +177,8 @@ var validLinkerFlags = []*regexp.Regexp{ ...@@ -177,6 +177,8 @@ var validLinkerFlags = []*regexp.Regexp{
re(`-Wl,-framework,[^,@\-][^,]+`), re(`-Wl,-framework,[^,@\-][^,]+`),
re(`-Wl,-headerpad_max_install_names`), re(`-Wl,-headerpad_max_install_names`),
re(`-Wl,--no-undefined`), re(`-Wl,--no-undefined`),
re(`-Wl,-R([^@\-][^,@]*$)`),
re(`-Wl,--just-symbols[=,]([^,@\-][^,@]+)`),
re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`), re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`),
re(`-Wl,-s`), re(`-Wl,-s`),
re(`-Wl,-search_paths_first`), re(`-Wl,-search_paths_first`),
...@@ -206,6 +208,8 @@ var validLinkerFlagsWithNextArg = []string{ ...@@ -206,6 +208,8 @@ var validLinkerFlagsWithNextArg = []string{
"-target", "-target",
"-Wl,-framework", "-Wl,-framework",
"-Wl,-rpath", "-Wl,-rpath",
"-Wl,-R",
"-Wl,--just-symbols",
"-Wl,-undefined", "-Wl,-undefined",
} }
......
...@@ -125,6 +125,11 @@ var goodLinkerFlags = [][]string{ ...@@ -125,6 +125,11 @@ var goodLinkerFlags = [][]string{
{"-pthread"}, {"-pthread"},
{"-Wl,-rpath,foo"}, {"-Wl,-rpath,foo"},
{"-Wl,-rpath,$ORIGIN/foo"}, {"-Wl,-rpath,$ORIGIN/foo"},
{"-Wl,-R", "/foo"},
{"-Wl,-R", "foo"},
{"-Wl,-R,foo"},
{"-Wl,--just-symbols=foo"},
{"-Wl,--just-symbols,foo"},
{"-Wl,--warn-error"}, {"-Wl,--warn-error"},
{"-Wl,--no-warn-error"}, {"-Wl,--no-warn-error"},
{"foo.so"}, {"foo.so"},
...@@ -197,6 +202,9 @@ var badLinkerFlags = [][]string{ ...@@ -197,6 +202,9 @@ var badLinkerFlags = [][]string{
{"-x", "--c"}, {"-x", "--c"},
{"-x", "@obj"}, {"-x", "@obj"},
{"-Wl,-rpath,@foo"}, {"-Wl,-rpath,@foo"},
{"-Wl,-R,foo,bar"},
{"-Wl,-R,@foo"},
{"-Wl,--just-symbols,@foo"},
{"../x.o"}, {"../x.o"},
} }
......
...@@ -662,9 +662,11 @@ func Asmbmacho(ctxt *Link) { ...@@ -662,9 +662,11 @@ func Asmbmacho(ctxt *Link) {
// and we can assume OS X. // and we can assume OS X.
// //
// See golang.org/issues/12941. // See golang.org/issues/12941.
//
// The version must be at least 10.9; see golang.org/issues/30488.
ml := newMachoLoad(ctxt.Arch, LC_VERSION_MIN_MACOSX, 2) ml := newMachoLoad(ctxt.Arch, LC_VERSION_MIN_MACOSX, 2)
ml.data[0] = 10<<16 | 7<<8 | 0<<0 // OS X version 10.7.0 ml.data[0] = 10<<16 | 9<<8 | 0<<0 // OS X version 10.9.0
ml.data[1] = 10<<16 | 7<<8 | 0<<0 // SDK 10.7.0 ml.data[1] = 10<<16 | 9<<8 | 0<<0 // SDK 10.9.0
} }
a := machowrite(ctxt.Arch, ctxt.Out, ctxt.LinkMode) a := machowrite(ctxt.Arch, ctxt.Out, ctxt.LinkMode)
......
...@@ -325,7 +325,7 @@ func (ctxt *Link) pclntab() { ...@@ -325,7 +325,7 @@ func (ctxt *Link) pclntab() {
// set the resumption point to PC_B. // set the resumption point to PC_B.
lastWasmAddr = uint32(r.Add) lastWasmAddr = uint32(r.Add)
} }
if r.Sym != nil && r.Sym.Name == "runtime.deferreturn" && r.Add == 0 { if r.Type.IsDirectJump() && r.Sym != nil && r.Sym.Name == "runtime.deferreturn" {
if ctxt.Arch.Family == sys.Wasm { if ctxt.Arch.Family == sys.Wasm {
deferreturn = lastWasmAddr deferreturn = lastWasmAddr
} else { } else {
......
package main package main
import ( import (
"debug/macho"
"internal/testenv" "internal/testenv"
"io/ioutil" "io/ioutil"
"os" "os"
...@@ -171,3 +172,67 @@ main.x: relocation target main.zero not defined ...@@ -171,3 +172,67 @@ main.x: relocation target main.zero not defined
t.Fatalf("want:\n%sgot:\n%s", want, got) t.Fatalf("want:\n%sgot:\n%s", want, got)
} }
} }
var testMacOSVersionSrc = `
package main
func main() { }
`
func TestMacOSVersion(t *testing.T) {
testenv.MustHaveGoBuild(t)
tmpdir, err := ioutil.TempDir("", "TestMacOSVersion")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
src := filepath.Join(tmpdir, "main.go")
err = ioutil.WriteFile(src, []byte(testMacOSVersionSrc), 0666)
if err != nil {
t.Fatal(err)
}
exe := filepath.Join(tmpdir, "main")
cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal", "-o", exe, src)
cmd.Env = append(os.Environ(),
"CGO_ENABLED=0",
"GOOS=darwin",
"GOARCH=amd64",
)
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
}
exef, err := os.Open(exe)
if err != nil {
t.Fatal(err)
}
exem, err := macho.NewFile(exef)
if err != nil {
t.Fatal(err)
}
found := false
const LC_VERSION_MIN_MACOSX = 0x24
checkMin := func(ver uint32) {
major, minor := (ver>>16)&0xff, (ver>>8)&0xff
if major != 10 || minor < 9 {
t.Errorf("LC_VERSION_MIN_MACOSX version %d.%d < 10.9", major, minor)
}
}
for _, cmd := range exem.Loads {
raw := cmd.Raw()
type_ := exem.ByteOrder.Uint32(raw)
if type_ != LC_VERSION_MIN_MACOSX {
continue
}
osVer := exem.ByteOrder.Uint32(raw[8:])
checkMin(osVer)
sdkVer := exem.ByteOrder.Uint32(raw[12:])
checkMin(sdkVer)
found = true
break
}
if !found {
t.Errorf("no LC_VERSION_MIN_MACOSX load command found")
}
}
...@@ -16,7 +16,7 @@ package x509 ...@@ -16,7 +16,7 @@ package x509
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h> #include <Security/Security.h>
static bool isSSLPolicy(SecPolicyRef policyRef) { static Boolean isSSLPolicy(SecPolicyRef policyRef) {
if (!policyRef) { if (!policyRef) {
return false; return false;
} }
...@@ -24,13 +24,13 @@ static bool isSSLPolicy(SecPolicyRef policyRef) { ...@@ -24,13 +24,13 @@ static bool isSSLPolicy(SecPolicyRef policyRef) {
if (properties == NULL) { if (properties == NULL) {
return false; return false;
} }
Boolean isSSL = false;
CFTypeRef value = NULL; CFTypeRef value = NULL;
if (CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value)) { if (CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value)) {
CFRelease(properties); isSSL = CFEqual(value, kSecPolicyAppleSSL);
return CFEqual(value, kSecPolicyAppleSSL);
} }
CFRelease(properties); CFRelease(properties);
return false; return isSSL;
} }
// sslTrustSettingsResult obtains the final kSecTrustSettingsResult value // sslTrustSettingsResult obtains the final kSecTrustSettingsResult value
......
...@@ -305,3 +305,6 @@ const ( ...@@ -305,3 +305,6 @@ const (
func LoadGetFinalPathNameByHandle() error { func LoadGetFinalPathNameByHandle() error {
return procGetFinalPathNameByHandleW.Find() return procGetFinalPathNameByHandleW.Find()
} }
//sys CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
//sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
...@@ -58,6 +58,8 @@ var ( ...@@ -58,6 +58,8 @@ var (
procNetShareAdd = modnetapi32.NewProc("NetShareAdd") procNetShareAdd = modnetapi32.NewProc("NetShareAdd")
procNetShareDel = modnetapi32.NewProc("NetShareDel") procNetShareDel = modnetapi32.NewProc("NetShareDel")
procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW") procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW")
procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock")
procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock")
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
...@@ -220,6 +222,36 @@ func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSiz ...@@ -220,6 +222,36 @@ func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSiz
return return
} }
func CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) {
var _p0 uint32
if inheritExisting {
_p0 = 1
} else {
_p0 = 0
}
r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0))
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func DestroyEnvironmentBlock(block *uint16) (err error) {
r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func ImpersonateSelf(impersonationlevel uint32) (err error) { func ImpersonateSelf(impersonationlevel uint32) (err error) {
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
if r1 == 0 { if r1 == 0 {
......
...@@ -33,6 +33,7 @@ var ( ...@@ -33,6 +33,7 @@ var (
ExportHttp2ConfigureServer = http2ConfigureServer ExportHttp2ConfigureServer = http2ConfigureServer
Export_shouldCopyHeaderOnRedirect = shouldCopyHeaderOnRedirect Export_shouldCopyHeaderOnRedirect = shouldCopyHeaderOnRedirect
Export_writeStatusLine = writeStatusLine Export_writeStatusLine = writeStatusLine
Export_is408Message = is408Message
) )
const MaxWriteWaitBeforeConnReuse = maxWriteWaitBeforeConnReuse const MaxWriteWaitBeforeConnReuse = maxWriteWaitBeforeConnReuse
......
...@@ -1826,7 +1826,12 @@ func (pc *persistConn) readLoopPeekFailLocked(peekErr error) { ...@@ -1826,7 +1826,12 @@ func (pc *persistConn) readLoopPeekFailLocked(peekErr error) {
} }
if n := pc.br.Buffered(); n > 0 { if n := pc.br.Buffered(); n > 0 {
buf, _ := pc.br.Peek(n) buf, _ := pc.br.Peek(n)
log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf, peekErr) if is408Message(buf) {
pc.closeLocked(errServerClosedIdle)
return
} else {
log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf, peekErr)
}
} }
if peekErr == io.EOF { if peekErr == io.EOF {
// common case. // common case.
...@@ -1836,6 +1841,19 @@ func (pc *persistConn) readLoopPeekFailLocked(peekErr error) { ...@@ -1836,6 +1841,19 @@ func (pc *persistConn) readLoopPeekFailLocked(peekErr error) {
} }
} }
// is408Message reports whether buf has the prefix of an
// HTTP 408 Request Timeout response.
// See golang.org/issue/32310.
func is408Message(buf []byte) bool {
if len(buf) < len("HTTP/1.x 408") {
return false
}
if string(buf[:7]) != "HTTP/1." {
return false
}
return string(buf[8:12]) == " 408"
}
// readResponse reads an HTTP response (or two, in the case of "Expect: // readResponse reads an HTTP response (or two, in the case of "Expect:
// 100-continue") from the server. It returns the final non-100 one. // 100-continue") from the server. It returns the final non-100 one.
// trace is optional. // trace is optional.
......
...@@ -5059,3 +5059,77 @@ func TestTransportRequestReplayable(t *testing.T) { ...@@ -5059,3 +5059,77 @@ func TestTransportRequestReplayable(t *testing.T) {
}) })
} }
} }
func TestIs408(t *testing.T) {
tests := []struct {
in string
want bool
}{
{"HTTP/1.0 408", true},
{"HTTP/1.1 408", true},
{"HTTP/1.8 408", true},
{"HTTP/2.0 408", false}, // maybe h2c would do this? but false for now.
{"HTTP/1.1 408 ", true},
{"HTTP/1.1 40", false},
{"http/1.0 408", false},
{"HTTP/1-1 408", false},
}
for _, tt := range tests {
if got := Export_is408Message([]byte(tt.in)); got != tt.want {
t.Errorf("is408Message(%q) = %v; want %v", tt.in, got, tt.want)
}
}
}
func TestTransportIgnores408(t *testing.T) {
// Not parallel. Relies on mutating the log package's global Output.
defer log.SetOutput(os.Stderr)
var logout bytes.Buffer
log.SetOutput(&logout)
defer afterTest(t)
const target = "backend:443"
cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
nc, _, err := w.(Hijacker).Hijack()
if err != nil {
t.Error(err)
return
}
defer nc.Close()
nc.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok"))
nc.Write([]byte("HTTP/1.1 408 bye\r\n")) // changing 408 to 409 makes test fail
}))
defer cst.close()
req, err := NewRequest("GET", cst.ts.URL, nil)
if err != nil {
t.Fatal(err)
}
res, err := cst.c.Do(req)
if err != nil {
t.Fatal(err)
}
slurp, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatal(err)
}
if err != nil {
t.Fatal(err)
}
if string(slurp) != "ok" {
t.Fatalf("got %q; want ok", slurp)
}
t0 := time.Now()
for i := 0; i < 50; i++ {
time.Sleep(time.Duration(i) * 5 * time.Millisecond)
if cst.tr.IdleConnKeyCountForTesting() == 0 {
if got := logout.String(); got != "" {
t.Fatalf("expected no log output; got: %s", got)
}
return
}
}
t.Fatalf("timeout after %v waiting for Transport connections to die off", time.Since(t0))
}
// Copyright 2019 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 !windows
package os
import "syscall"
func environForSysProcAttr(sys *syscall.SysProcAttr) ([]string, error) {
return Environ(), nil
}
// Copyright 2019 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 os
import (
"internal/syscall/windows"
"syscall"
"unicode/utf16"
"unsafe"
)
func environForSysProcAttr(sys *syscall.SysProcAttr) (env []string, err error) {
if sys == nil || sys.Token == 0 {
return Environ(), nil
}
var block *uint16
err = windows.CreateEnvironmentBlock(&block, sys.Token, false)
if err != nil {
return nil, err
}
defer windows.DestroyEnvironmentBlock(block)
blockp := uintptr(unsafe.Pointer(block))
for {
entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:]
for i, v := range entry {
if v == 0 {
entry = entry[:i]
break
}
}
if len(entry) == 0 {
break
}
env = append(env, string(utf16.Decode(entry)))
blockp += 2 * (uintptr(len(entry)) + 1)
}
return
}
...@@ -38,7 +38,10 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e ...@@ -38,7 +38,10 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e
Sys: attr.Sys, Sys: attr.Sys,
} }
if sysattr.Env == nil { if sysattr.Env == nil {
sysattr.Env = Environ() sysattr.Env, err = environForSysProcAttr(sysattr.Sys)
if err != nil {
return nil, err
}
} }
for _, f := range attr.Files { for _, f := range attr.Files {
sysattr.Files = append(sysattr.Files, f.Fd()) sysattr.Files = append(sysattr.Files, f.Fd())
......
// run
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
type container struct {
Value string
}
func main() {
s := []container{
7: {Value: "string value"},
}
if s[7].Value != "string value" {
panic(fmt.Errorf("wanted \"string value\", got \"%s\"", s[7].Value))
}
}
// run
// Copyright 2019 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.
// Make sure we use the deferreturn live map instead of
// the entry live map when handling a segv in a function
// that defers.
package main
import "runtime"
var finalized bool
var err string
type HeapObj [8]int64
const filler int64 = 0x123456789abcdef0
func (h *HeapObj) init() {
for i := 0; i < len(*h); i++ {
h[i] = filler
}
}
func (h *HeapObj) check() {
for i := 0; i < len(*h); i++ {
if h[i] != filler {
err = "filler overwritten"
}
}
}
func gc(shouldFinalize bool) {
runtime.GC()
runtime.GC()
runtime.GC()
if shouldFinalize != finalized {
err = "heap object finalized at the wrong time"
}
}
func main() {
h := new(HeapObj)
h.init()
runtime.SetFinalizer(h, func(h *HeapObj) {
finalized = true
})
gc(false)
g(h)
if err != "" {
panic(err)
}
}
func g(h *HeapObj) {
gc(false)
h.check()
// h is now unused
defer func() {
// h should not be live here. Previously we used to
// use the function entry point as the place to get
// the live map when handling a segv.
gc(true)
recover()
}()
*(*int)(nil) = 0 // trigger a segv
return
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment