diff options
34 files changed, 570 insertions, 111 deletions
@@ -3,7 +3,7 @@ Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. -![Gopher image](doc/gopher/fiveyears.jpg) +![Gopher image](https://golang.org/doc/gopher/fiveyears.jpg) *Gopher image by [Renee French][rf], licensed under [Creative Commons 3.0 Attributions license][cc3-by].* Our canonical Git repository is located at https://go.googlesource.com/go. diff --git a/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go index 9055dbda04..2d991012c8 100644 --- a/misc/cgo/testplugin/plugin_test.go +++ b/misc/cgo/testplugin/plugin_test.go @@ -201,12 +201,11 @@ func TestMethod(t *testing.T) { // Exported symbol's method must be live. goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go") goCmd(t, "build", "-o", "method.exe", "./method/main.go") + run(t, "./method.exe") +} - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - cmd := exec.CommandContext(ctx, "./method.exe") - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out) - } +func TestMethod2(t *testing.T) { + goCmd(t, "build", "-buildmode=plugin", "-o", "method2.so", "./method2/plugin.go") + goCmd(t, "build", "-o", "method2.exe", "./method2/main.go") + run(t, "./method2.exe") } diff --git a/misc/cgo/testplugin/testdata/method2/main.go b/misc/cgo/testplugin/testdata/method2/main.go new file mode 100644 index 0000000000..6a87e7b6a0 --- /dev/null +++ b/misc/cgo/testplugin/testdata/method2/main.go @@ -0,0 +1,32 @@ +// Copyright 2021 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. + +// A type can be passed to a plugin and converted to interface +// there. So its methods need to be live. + +package main + +import ( + "plugin" + + "testplugin/method2/p" +) + +var t p.T + +type I interface { M() } + +func main() { + pl, err := plugin.Open("method2.so") + if err != nil { + panic(err) + } + + f, err := pl.Lookup("F") + if err != nil { + panic(err) + } + + f.(func(p.T) interface{})(t).(I).M() +} diff --git a/misc/cgo/testplugin/testdata/method2/p/p.go b/misc/cgo/testplugin/testdata/method2/p/p.go new file mode 100644 index 0000000000..acb526acec --- /dev/null +++ b/misc/cgo/testplugin/testdata/method2/p/p.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T int + +func (T) M() { println("M") } diff --git a/misc/cgo/testplugin/testdata/method2/plugin.go b/misc/cgo/testplugin/testdata/method2/plugin.go new file mode 100644 index 0000000000..6198e7648e --- /dev/null +++ b/misc/cgo/testplugin/testdata/method2/plugin.go @@ -0,0 +1,11 @@ +// Copyright 2021 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 "testplugin/method2/p" + +func main() {} + +func F(t p.T) interface{} { return t } diff --git a/src/cmd/compile/internal/gc/dwinl.go b/src/cmd/compile/internal/gc/dwinl.go index bb5ae61cbb..31d076814c 100644 --- a/src/cmd/compile/internal/gc/dwinl.go +++ b/src/cmd/compile/internal/gc/dwinl.go @@ -243,7 +243,8 @@ func makePreinlineDclMap(fnsym *obj.LSym) map[varPos]int { DeclCol: pos.Col(), } if _, found := m[vp]; found { - Fatalf("child dcl collision on symbol %s within %v\n", n.Sym.Name, fnsym.Name) + // We can see collisions (variables with the same name/file/line/col) in obfuscated or machine-generated code -- see issue 44378 for an example. Skip duplicates in such cases, since it is unlikely that a human will be debugging such code. + continue } m[vp] = i } diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 618bdf78e2..f719892d17 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1376,9 +1376,10 @@ func containsClosure(f, c *Node) bool { // leak records that parameter l leaks to sink. func (l *EscLocation) leakTo(sink *EscLocation, derefs int) { - // If sink is a result parameter and we can fit return bits - // into the escape analysis tag, then record a return leak. - if sink.isName(PPARAMOUT) && sink.curfn == l.curfn { + // If sink is a result parameter that doesn't escape (#44614) + // and we can fit return bits into the escape analysis tag, + // then record as a result leak. + if !sink.escapes && sink.isName(PPARAMOUT) && sink.curfn == l.curfn { // TODO(mdempsky): Eliminate dependency on Vargen here. ri := int(sink.n.Name.Vargen) - 1 if ri < numEscResults { diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 600d12b59b..a8cc01082a 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -1053,18 +1053,26 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { } } + // We can delay declaring+initializing result parameters if: + // (1) there's exactly one "return" statement in the inlined function; + // (2) it's not an empty return statement (#44355); and + // (3) the result parameters aren't named. + delayretvars := true + nreturns := 0 inspectList(asNodes(fn.Func.Inl.Body), func(n *Node) bool { if n != nil && n.Op == ORETURN { nreturns++ + if n.List.Len() == 0 { + delayretvars = false // empty return statement (case 2) + } } return true }) - // We can delay declaring+initializing result parameters if: - // (1) there's only one "return" statement in the inlined - // function, and (2) the result parameters aren't named. - delayretvars := nreturns == 1 + if nreturns != 1 { + delayretvars = false // not exactly one return statement (case 1) + } // temporaries for return values. var retvars []*Node @@ -1074,7 +1082,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { m = inlvar(n) m = typecheck(m, ctxExpr) inlvars[n] = m - delayretvars = false // found a named result parameter + delayretvars = false // found a named result parameter (case 3) } else { // anonymous return values, synthesize names for use in assignment that replaces return m = retvar(t, i) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 98ebb23991..02a7269ff8 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -3927,15 +3927,22 @@ func wrapCall(n *Node, init *Nodes) *Node { } } + wrapArgs := n.List.Slice() + // If there's a receiver argument, it needs to be passed through the wrapper too. + if n.Op == OCALLMETH || n.Op == OCALLINTER { + recv := n.Left.Left + wrapArgs = append([]*Node{recv}, wrapArgs...) + } + // origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion. - origArgs := make([]*Node, n.List.Len()) + origArgs := make([]*Node, len(wrapArgs)) t := nod(OTFUNC, nil, nil) - for i, arg := range n.List.Slice() { + for i, arg := range wrapArgs { s := lookupN("a", i) if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.IsUintptr() && arg.Left.Type.IsUnsafePtr() { origArgs[i] = arg arg = arg.Left - n.List.SetIndex(i, arg) + wrapArgs[i] = arg } t.List.Append(symfield(s, arg.Type)) } @@ -3953,6 +3960,12 @@ func wrapCall(n *Node, init *Nodes) *Node { arg.Type = origArg.Type args[i] = arg } + if n.Op == OCALLMETH || n.Op == OCALLINTER { + // Move wrapped receiver argument back to its appropriate place. + recv := typecheck(args[0], ctxExpr) + n.Left.Left = recv + args = args[1:] + } call := nod(n.Op, nil, nil) if !isBuiltinCall { call.Op = OCALL @@ -3970,7 +3983,7 @@ func wrapCall(n *Node, init *Nodes) *Node { call = nod(OCALL, nil, nil) call.Left = fn.Func.Nname - call.List.Set(n.List.Slice()) + call.List.Set(wrapArgs) call = typecheck(call, ctxStmt) call = walkexpr(call, init) return call diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 235e28f64f..35582f3975 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -6,7 +6,7 @@ require ( github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/mod v0.4.1 + golang.org/x/mod v0.4.2-0.20210302225053-d515b24adc21 golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 70aae0b4cc..10340d441f 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -14,8 +14,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2-0.20210302225053-d515b24adc21 h1:FnWKa8BJXkVQ+16E52jkfBOJPx2cG8y/6X376nOgSM4= +golang.org/x/mod v0.4.2-0.20210302225053-d515b24adc21/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index 38ff3823f2..329a2f5eda 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -431,7 +431,7 @@ func downloadPackage(p *load.Package) error { } importPrefix = importPrefix[:slash] } - if err := module.CheckImportPath(importPrefix); err != nil { + if err := checkImportPath(importPrefix); err != nil { return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err) } security := web.SecureOnly @@ -591,3 +591,31 @@ func selectTag(goVersion string, tags []string) (match string) { } return "" } + +// checkImportPath is like module.CheckImportPath, but it forbids leading dots +// in path elements. This can lead to 'go get' creating .git and other VCS +// directories in places we might run VCS tools later. +func checkImportPath(path string) error { + if err := module.CheckImportPath(path); err != nil { + return err + } + checkElem := func(elem string) error { + if elem[0] == '.' { + return fmt.Errorf("malformed import path %q: leading dot in path element", path) + } + return nil + } + elemStart := 0 + for i, r := range path { + if r == '/' { + if err := checkElem(path[elemStart:]); err != nil { + return err + } + elemStart = i + 1 + } + } + if err := checkElem(path[elemStart:]); err != nil { + return err + } + return nil +} diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index dccacd3d1e..5a98408a32 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -1514,7 +1514,7 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns } } if retractPath != "" { - fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest", retractPath) + fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest\n", retractPath) } } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index bc8d17e0a5..4de5ac9303 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -539,9 +539,10 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer { } } if vers != "" && module.CanonicalVersion(vers) == vers { - if err := module.CheckPathMajor(vers, pathMajor); err == nil { - return vers, nil + if err := module.CheckPathMajor(vers, pathMajor); err != nil { + return "", module.VersionError(module.Version{Path: path, Version: vers}, err) } + return vers, nil } info, err := Query(ctx, path, vers, "", nil) diff --git a/src/cmd/go/testdata/script/mod_edit.txt b/src/cmd/go/testdata/script/mod_edit.txt index d7e681e831..9da69306da 100644 --- a/src/cmd/go/testdata/script/mod_edit.txt +++ b/src/cmd/go/testdata/script/mod_edit.txt @@ -16,9 +16,9 @@ cmpenv go.mod $WORK/go.mod.init cmpenv go.mod $WORK/go.mod.init # go mod edits -go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' -retract=v1.6.0 -retract=[v1.1.0,v1.2.0] -retract=[v1.3.0,v1.4.0] -retract=v1.0.0 +go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -exclude=x.1@v2.0.0+incompatible -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' -retract=v1.6.0 -retract=[v1.1.0,v1.2.0] -retract=[v1.3.0,v1.4.0] -retract=v1.0.0 cmpenv go.mod $WORK/go.mod.edit1 -go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 -dropretract=v1.0.0 -dropretract=[v1.1.0,v1.2.0] +go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropexclude=x.1@v2.0.0+incompatible -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 -dropretract=v1.0.0 -dropretract=[v1.1.0,v1.2.0] cmpenv go.mod $WORK/go.mod.edit2 # -exclude and -retract reject invalid versions. @@ -27,6 +27,17 @@ stderr '^go mod: -exclude=example.com/m@bad: version "bad" invalid: must be of t ! go mod edit -retract=bad stderr '^go mod: -retract=bad: version "bad" invalid: must be of the form v1.2.3$' +! go mod edit -exclude=example.com/m@v2.0.0 +stderr '^go mod: -exclude=example.com/m@v2\.0\.0: version "v2\.0\.0" invalid: should be v2\.0\.0\+incompatible \(or module example\.com/m/v2\)$' + +! go mod edit -exclude=example.com/m/v2@v1.0.0 +stderr '^go mod: -exclude=example.com/m/v2@v1\.0\.0: version "v1\.0\.0" invalid: should be v2, not v1$' + +! go mod edit -exclude=gopkg.in/example.v1@v2.0.0 +stderr '^go mod: -exclude=gopkg\.in/example\.v1@v2\.0\.0: version "v2\.0\.0" invalid: should be v1, not v2$' + +cmpenv go.mod $WORK/go.mod.edit2 + # go mod edit -json go mod edit -json cmpenv stdout $WORK/go.mod.json @@ -88,6 +99,7 @@ require x.1 v1.0.0 exclude ( x.1 v1.2.0 x.1 v1.2.1 + x.1 v2.0.0+incompatible ) replace ( diff --git a/src/cmd/go/testdata/script/mod_get_retract.txt b/src/cmd/go/testdata/script/mod_get_retract.txt index fe0ac88629..560fa7bfb2 100644 --- a/src/cmd/go/testdata/script/mod_get_retract.txt +++ b/src/cmd/go/testdata/script/mod_get_retract.txt @@ -11,7 +11,7 @@ cp go.mod.orig go.mod go mod edit -require example.com/retract/self/prev@v1.9.0 go get -d example.com/retract/self/prev stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$' -stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest$' +stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest\n$' go list -m example.com/retract/self/prev stdout '^example.com/retract/self/prev v1.9.0$' diff --git a/src/cmd/go/testdata/script/mod_invalid_path.txt b/src/cmd/go/testdata/script/mod_invalid_path.txt index 667828839f..c8c075daae 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path.txt @@ -23,6 +23,20 @@ cd $WORK/gopath/src/badname ! go list . stderr 'invalid module path' +# Test that an import path containing an element with a leading dot is valid, +# but such a module path is not. +# Verifies #43985. +cd $WORK/gopath/src/dotname +go list ./.dot +stdout '^example.com/dotname/.dot$' +go list ./use +stdout '^example.com/dotname/use$' +! go list -m example.com/dotname/.dot@latest +stderr '^go list -m: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$' +go get -d example.com/dotname/.dot +go get -d example.com/dotname/use +go mod tidy + -- mod/go.mod -- -- mod/foo.go -- @@ -38,3 +52,13 @@ module .\. -- badname/foo.go -- package badname +-- dotname/go.mod -- +module example.com/dotname + +go 1.16 +-- dotname/.dot/dot.go -- +package dot +-- dotname/use/use.go -- +package use + +import _ "example.com/dotname/.dot" diff --git a/src/cmd/go/testdata/script/mod_retract_fix_version.txt b/src/cmd/go/testdata/script/mod_retract_fix_version.txt new file mode 100644 index 0000000000..e45758b627 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_retract_fix_version.txt @@ -0,0 +1,48 @@ +# retract must not be used without a module directive. +! go list -m all +stderr 'go.mod:3: no module directive found, so retract cannot be used$' + +# Commands that update go.mod should fix non-canonical versions in +# retract directives. +# Verifies #44494. +go mod edit -module=rsc.io/quote/v2 +! go list -m all +stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$' +go mod tidy +go list -m all +cmp go.mod go.mod.want + +# If a retracted version doesn't match the module's major version suffx, +# an error should be reported. +! go mod edit -retract=v3.0.1 +stderr '^go mod: -retract=v3.0.1: version "v3.0.1" invalid: should be v2, not v3$' +cp go.mod.mismatch-v2 go.mod +! go list -m all +stderr 'go.mod:3: retract rsc.io/quote/v2: version "v3.0.1" invalid: should be v2, not v3$' + +cp go.mod.mismatch-v1 go.mod +! go list -m all +stderr 'go.mod:3: retract rsc.io/quote: version "v3.0.1" invalid: should be v0 or v1, not v3$' + +-- go.mod -- +go 1.16 + +retract latest +-- go.mod.want -- +go 1.16 + +retract v2.0.1 + +module rsc.io/quote/v2 +-- go.mod.mismatch-v2 -- +go 1.16 + +retract v3.0.1 + +module rsc.io/quote/v2 +-- go.mod.mismatch-v1 -- +go 1.16 + +retract v3.0.1 + +module rsc.io/quote diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 245076a83a..bfa8640ba9 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -24,6 +24,7 @@ type deadcodePass struct { ifaceMethod map[methodsig]bool // methods declared in reached interfaces markableMethods []methodref // methods of reached types reflectSeen bool // whether we have seen a reflect method call + dynlink bool methodsigstmp []methodsig // scratch buffer for decoding method signatures } @@ -34,6 +35,7 @@ func (d *deadcodePass) init() { if objabi.Fieldtrack_enabled != 0 { d.ldr.Reachparent = make([]loader.Sym, d.ldr.NSym()) } + d.dynlink = d.ctxt.DynlinkingGo() if d.ctxt.BuildMode == BuildModeShared { // Mark all symbols defined in this library as reachable when @@ -111,6 +113,11 @@ func (d *deadcodePass) flood() { var usedInIface bool if isgotype { + if d.dynlink { + // When dynaamic linking, a type may be passed across DSO + // boundary and get converted to interface at the other side. + d.ldr.SetAttrUsedInIface(symIdx, true) + } usedInIface = d.ldr.AttrUsedInIface(symIdx) } diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go index c6a189dbe0..f8c9384985 100644 --- a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go +++ b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go @@ -125,6 +125,12 @@ func (f *File) AddComment(text string) { type VersionFixer func(path, version string) (string, error) +// errDontFix is returned by a VersionFixer to indicate the version should be +// left alone, even if it's not canonical. +var dontFixRetract VersionFixer = func(_, vers string) (string, error) { + return vers, nil +} + // Parse parses the data, reported in errors as being from file, // into a File struct. It applies fix, if non-nil, to canonicalize all module versions found. func Parse(file string, data []byte, fix VersionFixer) (*File, error) { @@ -142,7 +148,7 @@ func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) { return parseToFile(file, data, fix, false) } -func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File, error) { +func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parsed *File, err error) { fs, err := parse(file, data) if err != nil { return nil, err @@ -150,8 +156,18 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File f := &File{ Syntax: fs, } - var errs ErrorList + + // fix versions in retract directives after the file is parsed. + // We need the module path to fix versions, and it might be at the end. + defer func() { + oldLen := len(errs) + f.fixRetract(fix, &errs) + if len(errs) > oldLen { + parsed, err = nil, errs + } + }() + for _, x := range fs.Stmt { switch x := x.(type) { case *Line: @@ -370,7 +386,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a case "retract": rationale := parseRetractRationale(block, line) - vi, err := parseVersionInterval(verb, &args, fix) + vi, err := parseVersionInterval(verb, "", &args, dontFixRetract) if err != nil { if strict { wrapError(err) @@ -397,6 +413,47 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a } } +// fixRetract applies fix to each retract directive in f, appending any errors +// to errs. +// +// Most versions are fixed as we parse the file, but for retract directives, +// the relevant module path is the one specified with the module directive, +// and that might appear at the end of the file (or not at all). +func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) { + if fix == nil { + return + } + path := "" + if f.Module != nil { + path = f.Module.Mod.Path + } + var r *Retract + wrapError := func(err error) { + *errs = append(*errs, Error{ + Filename: f.Syntax.Name, + Pos: r.Syntax.Start, + Err: err, + }) + } + + for _, r = range f.Retract { + if path == "" { + wrapError(errors.New("no module directive found, so retract cannot be used")) + return // only print the first one of these + } + + args := r.Syntax.Token + if args[0] == "retract" { + args = args[1:] + } + vi, err := parseVersionInterval("retract", path, &args, fix) + if err != nil { + wrapError(err) + } + r.VersionInterval = vi + } +} + // isIndirect reports whether line has a "// indirect" comment, // meaning it is in go.mod only for its effect on indirect dependencies, // so that it can be dropped entirely once the effective version of the @@ -491,13 +548,13 @@ func AutoQuote(s string) string { return s } -func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (VersionInterval, error) { +func parseVersionInterval(verb string, path string, args *[]string, fix VersionFixer) (VersionInterval, error) { toks := *args if len(toks) == 0 || toks[0] == "(" { return VersionInterval{}, fmt.Errorf("expected '[' or version") } if toks[0] != "[" { - v, err := parseVersion(verb, "", &toks[0], fix) + v, err := parseVersion(verb, path, &toks[0], fix) if err != nil { return VersionInterval{}, err } @@ -509,7 +566,7 @@ func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (Versio if len(toks) == 0 { return VersionInterval{}, fmt.Errorf("expected version after '['") } - low, err := parseVersion(verb, "", &toks[0], fix) + low, err := parseVersion(verb, path, &toks[0], fix) if err != nil { return VersionInterval{}, err } @@ -523,7 +580,7 @@ func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (Versio if len(toks) == 0 { return VersionInterval{}, fmt.Errorf("expected version after ','") } - high, err := parseVersion(verb, "", &toks[0], fix) + high, err := parseVersion(verb, path, &toks[0], fix) if err != nil { return VersionInterval{}, err } @@ -631,8 +688,7 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string } } if fix != nil { - var err error - t, err = fix(path, t) + fixed, err := fix(path, t) if err != nil { if err, ok := err.(*module.ModuleError); ok { return "", &Error{ @@ -643,19 +699,23 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string } return "", err } + t = fixed + } else { + cv := module.CanonicalVersion(t) + if cv == "" { + return "", &Error{ + Verb: verb, + ModPath: path, + Err: &module.InvalidVersionError{ + Version: t, + Err: errors.New("must be of the form v1.2.3"), + }, + } + } + t = cv } - if v := module.CanonicalVersion(t); v != "" { - *s = v - return *s, nil - } - return "", &Error{ - Verb: verb, - ModPath: path, - Err: &module.InvalidVersionError{ - Version: t, - Err: errors.New("must be of the form v1.2.3"), - }, - } + *s = t + return *s, nil } func modulePathMajor(path string) (string, error) { @@ -835,11 +895,8 @@ func (f *File) DropRequire(path string) error { // AddExclude adds a exclude statement to the mod file. Errors if the provided // version is not a canonical version string func (f *File) AddExclude(path, vers string) error { - if !isCanonicalVersion(vers) { - return &module.InvalidVersionError{ - Version: vers, - Err: errors.New("must be of the form v1.2.3"), - } + if err := checkCanonicalVersion(path, vers); err != nil { + return err } var hint *Line @@ -916,17 +973,15 @@ func (f *File) DropReplace(oldPath, oldVers string) error { // AddRetract adds a retract statement to the mod file. Errors if the provided // version interval does not consist of canonical version strings func (f *File) AddRetract(vi VersionInterval, rationale string) error { - if !isCanonicalVersion(vi.High) { - return &module.InvalidVersionError{ - Version: vi.High, - Err: errors.New("must be of the form v1.2.3"), - } + var path string + if f.Module != nil { + path = f.Module.Mod.Path } - if !isCanonicalVersion(vi.Low) { - return &module.InvalidVersionError{ - Version: vi.Low, - Err: errors.New("must be of the form v1.2.3"), - } + if err := checkCanonicalVersion(path, vi.High); err != nil { + return err + } + if err := checkCanonicalVersion(path, vi.Low); err != nil { + return err } r := &Retract{ @@ -1086,8 +1141,40 @@ func lineRetractLess(li, lj *Line) bool { return semver.Compare(vii.High, vij.High) > 0 } -// isCanonicalVersion tests if the provided version string represents a valid -// canonical version. -func isCanonicalVersion(vers string) bool { - return vers != "" && semver.Canonical(vers) == vers +// checkCanonicalVersion returns a non-nil error if vers is not a canonical +// version string or does not match the major version of path. +// +// If path is non-empty, the error text suggests a format with a major version +// corresponding to the path. +func checkCanonicalVersion(path, vers string) error { + _, pathMajor, pathMajorOk := module.SplitPathVersion(path) + + if vers == "" || vers != module.CanonicalVersion(vers) { + if pathMajor == "" { + return &module.InvalidVersionError{ + Version: vers, + Err: fmt.Errorf("must be of the form v1.2.3"), + } + } + return &module.InvalidVersionError{ + Version: vers, + Err: fmt.Errorf("must be of the form %s.2.3", module.PathMajorPrefix(pathMajor)), + } + } + + if pathMajorOk { + if err := module.CheckPathMajor(vers, pathMajor); err != nil { + if pathMajor == "" { + // In this context, the user probably wrote "v2.3.4" when they meant + // "v2.3.4+incompatible". Suggest that instead of "v0 or v1". + return &module.InvalidVersionError{ + Version: vers, + Err: fmt.Errorf("should be %s+incompatible (or module %s/%v)", vers, path, semver.Major(vers)), + } + } + return err + } + } + + return nil } diff --git a/src/cmd/vendor/golang.org/x/mod/module/module.go b/src/cmd/vendor/golang.org/x/mod/module/module.go index c1c5263c42..272baeef17 100644 --- a/src/cmd/vendor/golang.org/x/mod/module/module.go +++ b/src/cmd/vendor/golang.org/x/mod/module/module.go @@ -270,7 +270,7 @@ func fileNameOK(r rune) bool { // CheckPath checks that a module path is valid. // A valid module path is a valid import path, as checked by CheckImportPath, -// with two additional constraints. +// with three additional constraints. // First, the leading path element (up to the first slash, if any), // by convention a domain name, must contain only lower-case ASCII letters, // ASCII digits, dots (U+002E), and dashes (U+002D); @@ -280,8 +280,9 @@ func fileNameOK(r rune) bool { // and must not contain any dots. For paths beginning with "gopkg.in/", // this second requirement is replaced by a requirement that the path // follow the gopkg.in server's conventions. +// Third, no path element may begin with a dot. func CheckPath(path string) error { - if err := checkPath(path, false); err != nil { + if err := checkPath(path, modulePath); err != nil { return fmt.Errorf("malformed module path %q: %v", path, err) } i := strings.Index(path, "/") @@ -315,7 +316,7 @@ func CheckPath(path string) error { // // A valid path element is a non-empty string made up of // ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~. -// It must not begin or end with a dot (U+002E), nor contain two dots in a row. +// It must not end with a dot (U+002E), nor contain two dots in a row. // // The element prefix up to the first dot must not be a reserved file name // on Windows, regardless of case (CON, com1, NuL, and so on). The element @@ -326,19 +327,29 @@ func CheckPath(path string) error { // top-level package documentation for additional information about // subtleties of Unicode. func CheckImportPath(path string) error { - if err := checkPath(path, false); err != nil { + if err := checkPath(path, importPath); err != nil { return fmt.Errorf("malformed import path %q: %v", path, err) } return nil } +// pathKind indicates what kind of path we're checking. Module paths, +// import paths, and file paths have different restrictions. +type pathKind int + +const ( + modulePath pathKind = iota + importPath + filePath +) + // checkPath checks that a general path is valid. // It returns an error describing why but not mentioning path. // Because these checks apply to both module paths and import paths, // the caller is expected to add the "malformed ___ path %q: " prefix. // fileName indicates whether the final element of the path is a file name // (as opposed to a directory name). -func checkPath(path string, fileName bool) error { +func checkPath(path string, kind pathKind) error { if !utf8.ValidString(path) { return fmt.Errorf("invalid UTF-8") } @@ -357,35 +368,34 @@ func checkPath(path string, fileName bool) error { elemStart := 0 for i, r := range path { if r == '/' { - if err := checkElem(path[elemStart:i], fileName); err != nil { + if err := checkElem(path[elemStart:i], kind); err != nil { return err } elemStart = i + 1 } } - if err := checkElem(path[elemStart:], fileName); err != nil { + if err := checkElem(path[elemStart:], kind); err != nil { return err } return nil } // checkElem checks whether an individual path element is valid. -// fileName indicates whether the element is a file name (not a directory name). -func checkElem(elem string, fileName bool) error { +func checkElem(elem string, kind pathKind) error { if elem == "" { return fmt.Errorf("empty path element") } if strings.Count(elem, ".") == len(elem) { return fmt.Errorf("invalid path element %q", elem) } - if elem[0] == '.' && !fileName { + if elem[0] == '.' && kind == modulePath { return fmt.Errorf("leading dot in path element") } if elem[len(elem)-1] == '.' { return fmt.Errorf("trailing dot in path element") } charOK := pathOK - if fileName { + if kind == filePath { charOK = fileNameOK } for _, r := range elem { @@ -406,7 +416,7 @@ func checkElem(elem string, fileName bool) error { } } - if fileName { + if kind == filePath { // don't check for Windows short-names in file names. They're // only an issue for import paths. return nil @@ -444,7 +454,7 @@ func checkElem(elem string, fileName bool) error { // top-level package documentation for additional information about // subtleties of Unicode. func CheckFilePath(path string) error { - if err := checkPath(path, true); err != nil { + if err := checkPath(path, filePath); err != nil { return fmt.Errorf("malformed file path %q: %v", path, err) } return nil @@ -647,7 +657,7 @@ func EscapePath(path string) (escaped string, err error) { // Versions are allowed to be in non-semver form but must be valid file names // and not contain exclamation marks. func EscapeVersion(v string) (escaped string, err error) { - if err := checkElem(v, true); err != nil || strings.Contains(v, "!") { + if err := checkElem(v, filePath); err != nil || strings.Contains(v, "!") { return "", &InvalidVersionError{ Version: v, Err: fmt.Errorf("disallowed version string"), @@ -706,7 +716,7 @@ func UnescapeVersion(escaped string) (v string, err error) { if !ok { return "", fmt.Errorf("invalid escaped version %q", escaped) } - if err := checkElem(v, true); err != nil { + if err := checkElem(v, filePath); err != nil { return "", fmt.Errorf("invalid escaped version %q: %v", v, err) } return v, nil diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index e033984956..10842768a8 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 golang.org/x/crypto/ssh/terminal -# golang.org/x/mod v0.4.1 +# golang.org/x/mod v0.4.2-0.20210302225053-d515b24adc21 ## explicit golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile diff --git a/src/runtime/cgo/linux_syscall.c b/src/runtime/cgo/linux_syscall.c index 56f3d67d8b..59761c8b40 100644 --- a/src/runtime/cgo/linux_syscall.c +++ b/src/runtime/cgo/linux_syscall.c @@ -32,7 +32,7 @@ typedef struct { #define SET_RETVAL(fn) \ uintptr_t ret = (uintptr_t) fn ; \ - if (ret == -1) { \ + if (ret == (uintptr_t) -1) { \ x->retval = (uintptr_t) errno; \ } else \ x->retval = ret diff --git a/src/syscall/ptrace_ios.go b/src/syscall/ptrace_ios.go index 2f61a88a08..5209d1e0dd 100644 --- a/src/syscall/ptrace_ios.go +++ b/src/syscall/ptrace_ios.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ios +// +build ios + package syscall // Nosplit because it is called from forkAndExecInChild. diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index ba69133d81..69cef52545 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -213,9 +213,9 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetEndOfFile(handle Handle) (err error) //sys GetSystemTimeAsFileTime(time *Filetime) //sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] -//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) -//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) -//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) +//sys createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) = CreateIoCompletionPort +//sys getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) = GetQueuedCompletionStatus +//sys postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) = PostQueuedCompletionStatus //sys CancelIo(s Handle) (err error) //sys CancelIoEx(s Handle, o *Overlapped) (err error) //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW @@ -1209,3 +1209,31 @@ func Readlink(path string, buf []byte) (n int, err error) { return n, nil } + +// Deprecated: CreateIoCompletionPort has the wrong function signature. Use x/sys/windows.CreateIoCompletionPort. +func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) { + return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt) +} + +// Deprecated: GetQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.GetQueuedCompletionStatus. +func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error { + var ukey uintptr + var pukey *uintptr + if key != nil { + ukey = uintptr(*key) + pukey = &ukey + } + err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout) + if key != nil { + *key = uint32(ukey) + if uintptr(*key) != ukey && err == nil { + err = errorspkg.New("GetQueuedCompletionStatus returned key overflow") + } + } + return err +} + +// Deprecated: PostQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.PostQueuedCompletionStatus. +func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error { + return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped) +} diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go index 2166be595b..b1480ba7df 100644 --- a/src/syscall/zsyscall_windows.go +++ b/src/syscall/zsyscall_windows.go @@ -515,7 +515,7 @@ func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr return } -func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { +func createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) { r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) handle = Handle(r0) if handle == 0 { @@ -822,7 +822,7 @@ func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, return } -func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { +func getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) { r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) if r1 == 0 { err = errnoErr(e1) @@ -954,7 +954,7 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err return } -func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { +func postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) { r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) if r1 == 0 { err = errnoErr(e1) diff --git a/src/time/zoneinfo.go b/src/time/zoneinfo.go index c3662297c7..6db9443474 100644 --- a/src/time/zoneinfo.go +++ b/src/time/zoneinfo.go @@ -377,8 +377,10 @@ func tzsetOffset(s string) (offset int, rest string, ok bool) { neg = true } + // The tzdata code permits values up to 24 * 7 here, + // although POSIX does not. var hours int - hours, s, ok = tzsetNum(s, 0, 24) + hours, s, ok = tzsetNum(s, 0, 24*7) if !ok { return 0, "", false } @@ -487,7 +489,7 @@ func tzsetRule(s string) (rule, string, bool) { } offset, s, ok := tzsetOffset(s[1:]) - if !ok || offset < 0 { + if !ok { return rule{}, "", false } r.time = offset diff --git a/src/time/zoneinfo_test.go b/src/time/zoneinfo_test.go index 277b68f798..d043e1e9f1 100644 --- a/src/time/zoneinfo_test.go +++ b/src/time/zoneinfo_test.go @@ -183,22 +183,50 @@ func TestMalformedTZData(t *testing.T) { } } -func TestLoadLocationFromTZDataSlim(t *testing.T) { - // A 2020b slim tzdata for Europe/Berlin - tzData := "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\f\x88\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\rLMT\x00CEST\x00CET\x00CEMT\x00\nCET-1CEST,M3.5.0,M10.5.0/3\n" +var slimTests = []struct { + zoneName string + tzData string + wantName string + wantOffset int +}{ + { + // 2020b slim tzdata for Europe/Berlin. + zoneName: "Europe/Berlin", + tzData: "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\f\x88\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\rLMT\x00CEST\x00CET\x00CEMT\x00\nCET-1CEST,M3.5.0,M10.5.0/3\n", + wantName: "CET", + wantOffset: 3600, + }, + { + // 2021a slim tzdata for America/Nuuk. + zoneName: "America/Nuuk", + tzData: "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80h\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xffπ\x00\x00\xff\xff\xd5\xd0\x00\x04\xff\xff\xe3\xe0\x01\bLMT\x00-03\x00-02\x00\n<-03>3<-02>,M3.5.0/-2,M10.5.0/-1\n", + wantName: "-03", + wantOffset: -10800, + }, + { + // 2021a slim tzdata for Asia/Gaza. + zoneName: "Asia/Gaza", + tzData: "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\xb0\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xad.\x9c\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 P\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11LMT\x00EEST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.4.4/49\n", + wantName: "EET", + wantOffset: 7200, + }, +} - reference, err := time.LoadLocationFromTZData("Europe/Berlin", []byte(tzData)) - if err != nil { - t.Fatal(err) - } +func TestLoadLocationFromTZDataSlim(t *testing.T) { + for _, test := range slimTests { + reference, err := time.LoadLocationFromTZData(test.zoneName, []byte(test.tzData)) + if err != nil { + t.Fatal(err) + } - d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference) - tzName, tzOffset := d.Zone() - if want := "CET"; tzName != want { - t.Errorf("Zone name == %s, want %s", tzName, want) - } - if want := 3600; tzOffset != want { - t.Errorf("Zone offset == %d, want %d", tzOffset, want) + d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference) + tzName, tzOffset := d.Zone() + if tzName != test.wantName { + t.Errorf("Zone name == %s, want %s", tzName, test.wantName) + } + if tzOffset != test.wantOffset { + t.Errorf("Zone offset == %d, want %d", tzOffset, test.wantOffset) + } } } @@ -263,7 +291,8 @@ func TestTzsetOffset(t *testing.T) { {"+08", 8 * 60 * 60, "", true}, {"-01:02:03", -1*60*60 - 2*60 - 3, "", true}, {"01", 1 * 60 * 60, "", true}, - {"100", 0, "", false}, + {"100", 100 * 60 * 60, "", true}, + {"1000", 0, "", false}, {"8PDT", 8 * 60 * 60, "PDT", true}, } { off, out, ok := time.TzsetOffset(test.in) @@ -288,6 +317,7 @@ func TestTzsetRule(t *testing.T) { {"30/03:00:00", time.Rule{Kind: time.RuleDOY, Day: 30, Time: 3 * 60 * 60}, "", true}, {"M4.5.6/03:00:00", time.Rule{Kind: time.RuleMonthWeekDay, Mon: 4, Week: 5, Day: 6, Time: 3 * 60 * 60}, "", true}, {"M4.5.7/03:00:00", time.Rule{}, "", false}, + {"M4.5.6/-04", time.Rule{Kind: time.RuleMonthWeekDay, Mon: 4, Week: 5, Day: 6, Time: -4 * 60 * 60}, "", true}, } { r, out, ok := time.TzsetRule(test.in) if r != test.r || out != test.out || ok != test.ok { diff --git a/test/escape5.go b/test/escape5.go index 2ed2023cd2..82be2c38e7 100644 --- a/test/escape5.go +++ b/test/escape5.go @@ -269,3 +269,14 @@ func f28369(n int) int { return 1 + f28369(n-1) } + +// Issue 44614: parameters that flow to a heap-allocated result +// parameter must be recorded as a heap-flow rather than a +// result-flow. + +// N.B., must match "leaking param: p", +// but *not* "leaking param: p to result r level=0". +func f(p *int) (r *int) { // ERROR "leaking param: p$" "moved to heap: r" + sink4 = &r + return p +} diff --git a/test/fixedbugs/issue24491a.go b/test/fixedbugs/issue24491a.go index 8accf8c0a3..d30b65b233 100644 --- a/test/fixedbugs/issue24491a.go +++ b/test/fixedbugs/issue24491a.go @@ -48,6 +48,14 @@ func f() int { return test("return", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) } +type S struct{} + +//go:noinline +//go:uintptrescapes +func (S) test(s string, p, q uintptr, rest ...uintptr) int { + return test(s, p, q, rest...) +} + func main() { test("normal", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) <-done @@ -60,6 +68,29 @@ func main() { }() <-done + func() { + for { + defer test("defer in for loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + break + } + }() + + <-done + func() { + s := &S{} + defer s.test("method call", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + }() + <-done + + func() { + s := &S{} + for { + defer s.test("defer method loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + break + } + }() + <-done + f() <-done } diff --git a/test/fixedbugs/issue44355.dir/a.go b/test/fixedbugs/issue44355.dir/a.go new file mode 100644 index 0000000000..0f63c6fd98 --- /dev/null +++ b/test/fixedbugs/issue44355.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2021 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 + +func F() (_ *int) { return nil } diff --git a/test/fixedbugs/issue44355.dir/b.go b/test/fixedbugs/issue44355.dir/b.go new file mode 100644 index 0000000000..09d5bde887 --- /dev/null +++ b/test/fixedbugs/issue44355.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 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" + +var _ = a.F() diff --git a/test/fixedbugs/issue44355.go b/test/fixedbugs/issue44355.go new file mode 100644 index 0000000000..d406838588 --- /dev/null +++ b/test/fixedbugs/issue44355.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2021 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 ignored diff --git a/test/fixedbugs/issue44378.go b/test/fixedbugs/issue44378.go new file mode 100644 index 0000000000..58c88d573f --- /dev/null +++ b/test/fixedbugs/issue44378.go @@ -0,0 +1,40 @@ +// compile + +// Copyright 2021 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. + +// This test case caused a panic in the compiler's DWARF gen code. + +// Note to future maintainers of this code: +// +// ** Do NOT run gofmt when editing this file ** +// +// In order for the buggy behavior to be triggered in the compiler, +// we need to have a the function of interest all on one gigantic line. + +package a + +type O interface{} +type IO int +type OS int + +type A struct { + x int +} + +// original versions of the two function +func (p *A) UO(o O) { + p.r(o, o) +} +func (p *A) r(o1, o2 O) { + switch x := o1.(type) { + case *IO: + p.x = int(*x) + case *OS: + p.x = int(*x + 2) + } +} + +// see note above about the importance of all this code winding up on one line. +var myverylongname0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 int ; func (p *A) UO2(o O) { p.r2(o, o); }; func (p *A) r2(o1, o2 O) { switch x := o1.(type) { case *IO: p.x = int(*x); case *OS: p.x = int(*x + 2); } } |