diff mbox series

libgo patch committed: Update to Go 1.16.2 release

Message ID CAOyqgcX9vXgn4uhw5ZuQ43BfT2ArrNkEgMyvtrom8O7ddGVo1w@mail.gmail.com
State New
Headers show
Series libgo patch committed: Update to Go 1.16.2 release | expand

Commit Message

Ian Lance Taylor March 15, 2021, 9:53 p.m. UTC
This patch updates libgo to the Go 1.16.2 release.  Bootstrapped and
ran Go testsuite on x86_64-pc-linux-gnu.  Committed to mainline.

Ian
d5eae60451faeea9d87ae3815f7e4db0e6e182ed
diff mbox series

Patch

diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index e5756c6662c..c0bfa1ff78a 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@ 
-2f281eb24ef256a2d3bb9fc1a7ef964d82b40182
+10b00ad87303d37c68b2d54dd25d655bd316946e
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/libgo/MERGE b/libgo/MERGE
index 183b0245ee2..a52dceb182f 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@ 
-f21be2fdc6f1becdbed1592ea0b245cdeedc5ac8
+3979fb9af9ccfc0b7ccb613dcf256b18c2c295f0
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
diff --git a/libgo/VERSION b/libgo/VERSION
index 4befab24bc9..d0b0a900460 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@ 
-go1.16
+go1.16.2
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index 8b4e77875fb..c288ad965bc 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -664,7 +664,7 @@  func toValidName(name string) string {
 	if strings.HasPrefix(p, "/") {
 		p = p[len("/"):]
 	}
-	for strings.HasPrefix(name, "../") {
+	for strings.HasPrefix(p, "../") {
 		p = p[len("../"):]
 	}
 	return p
diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go
index 34e96f7da43..5faf1f49b51 100644
--- a/libgo/go/archive/zip/reader_test.go
+++ b/libgo/go/archive/zip/reader_test.go
@@ -1081,3 +1081,38 @@  func TestFS(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func TestCVE202127919(t *testing.T) {
+	// Archive containing only the file "../test.txt"
+	data := []byte{
+		0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
+		0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x2e,
+		0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
+		0x74, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0xc8, 0x2c,
+		0x56, 0x48, 0x54, 0x28, 0x49, 0x2d, 0x2e, 0x51,
+		0x28, 0x49, 0xad, 0x28, 0x51, 0x48, 0xcb, 0xcc,
+		0x49, 0xd5, 0xe3, 0x02, 0x04, 0x00, 0x00, 0xff,
+		0xff, 0x50, 0x4b, 0x07, 0x08, 0xc0, 0xd7, 0xed,
+		0xc3, 0x20, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
+		0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14,
+		0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0xc0, 0xd7, 0xed, 0xc3, 0x20, 0x00, 0x00,
+		0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
+		0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
+		0x78, 0x74, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00,
+		0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
+		0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}
+	r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
+	if err != nil {
+		t.Fatalf("Error reading the archive: %v", err)
+	}
+	_, err = r.Open("test.txt")
+	if err != nil {
+		t.Errorf("Error reading file: %v", err)
+	}
+}
diff --git a/libgo/go/cmd/go.mod b/libgo/go/cmd/go.mod
index 235e28f64f3..35582f3975f 100644
--- a/libgo/go/cmd/go.mod
+++ b/libgo/go/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/libgo/go/cmd/go/internal/get/get.go b/libgo/go/cmd/go/internal/get/get.go
index 38ff3823f22..329a2f5eda4 100644
--- a/libgo/go/cmd/go/internal/get/get.go
+++ b/libgo/go/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/libgo/go/cmd/go/internal/modcmd/tidy.go b/libgo/go/cmd/go/internal/modcmd/tidy.go
index 3b83d87a8eb..8bc9ed50bed 100644
--- a/libgo/go/cmd/go/internal/modcmd/tidy.go
+++ b/libgo/go/cmd/go/internal/modcmd/tidy.go
@@ -62,10 +62,11 @@  func runTidy(ctx context.Context, cmd *base.Command, args []string) {
 	modload.RootMode = modload.NeedRoot
 
 	modload.LoadPackages(ctx, modload.PackageOpts{
-		Tags:                  imports.AnyTags(),
-		ResolveMissingImports: true,
-		LoadTests:             true,
-		AllowErrors:           tidyE,
+		Tags:                     imports.AnyTags(),
+		ResolveMissingImports:    true,
+		LoadTests:                true,
+		AllowErrors:              tidyE,
+		SilenceMissingStdImports: true,
 	}, "all")
 
 	modload.TidyBuildList()
diff --git a/libgo/go/cmd/go/internal/modcmd/vendor.go b/libgo/go/cmd/go/internal/modcmd/vendor.go
index d3ed9e00e22..ac1fb7720aa 100644
--- a/libgo/go/cmd/go/internal/modcmd/vendor.go
+++ b/libgo/go/cmd/go/internal/modcmd/vendor.go
@@ -64,10 +64,11 @@  func runVendor(ctx context.Context, cmd *base.Command, args []string) {
 	modload.RootMode = modload.NeedRoot
 
 	loadOpts := modload.PackageOpts{
-		Tags:                  imports.AnyTags(),
-		ResolveMissingImports: true,
-		UseVendorAll:          true,
-		AllowErrors:           vendorE,
+		Tags:                     imports.AnyTags(),
+		ResolveMissingImports:    true,
+		UseVendorAll:             true,
+		AllowErrors:              vendorE,
+		SilenceMissingStdImports: true,
 	}
 	_, pkgs := modload.LoadPackages(ctx, loadOpts, "all")
 
diff --git a/libgo/go/cmd/go/internal/modget/get.go b/libgo/go/cmd/go/internal/modget/get.go
index dccacd3d1ee..5a98408a325 100644
--- a/libgo/go/cmd/go/internal/modget/get.go
+++ b/libgo/go/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/libgo/go/cmd/go/internal/modget/query.go b/libgo/go/cmd/go/internal/modget/query.go
index d8364c8c0d3..1a5a60f7eb9 100644
--- a/libgo/go/cmd/go/internal/modget/query.go
+++ b/libgo/go/cmd/go/internal/modget/query.go
@@ -186,7 +186,7 @@  func (q *query) validate() error {
 	if q.pattern == "all" {
 		// If there is no main module, "all" is not meaningful.
 		if !modload.HasModRoot() {
-			return fmt.Errorf(`cannot match "all": working directory is not part of a module`)
+			return fmt.Errorf(`cannot match "all": %v`, modload.ErrNoModRoot)
 		}
 		if !versionOkForMainModule(q.version) {
 			// TODO(bcmills): "all@none" seems like a totally reasonable way to
diff --git a/libgo/go/cmd/go/internal/modload/import.go b/libgo/go/cmd/go/internal/modload/import.go
index 182429aee41..995641c9f1f 100644
--- a/libgo/go/cmd/go/internal/modload/import.go
+++ b/libgo/go/cmd/go/internal/modload/import.go
@@ -51,7 +51,7 @@  func (e *ImportMissingError) Error() string {
 		if e.isStd {
 			return fmt.Sprintf("package %s is not in GOROOT (%s)", e.Path, filepath.Join(cfg.GOROOT, "src", e.Path))
 		}
-		if e.QueryErr != nil {
+		if e.QueryErr != nil && e.QueryErr != ErrNoModRoot {
 			return fmt.Sprintf("cannot find module providing package %s: %v", e.Path, e.QueryErr)
 		}
 		if cfg.BuildMod == "mod" || (cfg.BuildMod == "readonly" && allowMissingModuleImports) {
@@ -66,13 +66,11 @@  func (e *ImportMissingError) Error() string {
 			return fmt.Sprintf("module %s provides package %s and is replaced but not required; to add it:\n\tgo get %s", e.replaced.Path, e.Path, suggestArg)
 		}
 
-		suggestion := ""
-		if !HasModRoot() {
-			suggestion = ": working directory is not part of a module"
-		} else {
-			suggestion = fmt.Sprintf("; to add it:\n\tgo get %s", e.Path)
+		message := fmt.Sprintf("no required module provides package %s", e.Path)
+		if e.QueryErr != nil {
+			return fmt.Sprintf("%s: %v", message, e.QueryErr)
 		}
-		return fmt.Sprintf("no required module provides package %s%s", e.Path, suggestion)
+		return fmt.Sprintf("%s; to add it:\n\tgo get %s", message, e.Path)
 	}
 
 	if e.newMissingVersion != "" {
@@ -318,7 +316,11 @@  func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
 		return mods[0], dirs[0], nil
 	}
 
-	return module.Version{}, "", &ImportMissingError{Path: path, isStd: pathIsStd}
+	var queryErr error
+	if !HasModRoot() {
+		queryErr = ErrNoModRoot
+	}
+	return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd}
 }
 
 // queryImport attempts to locate a module that can be added to the current
diff --git a/libgo/go/cmd/go/internal/modload/init.go b/libgo/go/cmd/go/internal/modload/init.go
index bc8d17e0a5f..8ec1c8681a9 100644
--- a/libgo/go/cmd/go/internal/modload/init.go
+++ b/libgo/go/cmd/go/internal/modload/init.go
@@ -177,7 +177,7 @@  func Init() {
 				base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.")
 			}
 			if RootMode == NeedRoot {
-				base.Fatalf("go: cannot find main module; see 'go help modules'")
+				base.Fatalf("go: %v", ErrNoModRoot)
 			}
 			if !mustUseModules {
 				// GO111MODULE is 'auto', and we can't find a module root.
@@ -338,9 +338,11 @@  func die() {
 		}
 		base.Fatalf("go: cannot find main module, but found %s in %s\n\tto create a module there, run:\n\t%sgo mod init", name, dir, cdCmd)
 	}
-	base.Fatalf("go: cannot find main module; see 'go help modules'")
+	base.Fatalf("go: %v", ErrNoModRoot)
 }
 
+var ErrNoModRoot = errors.New("go.mod file not found in current directory or any parent directory; see 'go help modules'")
+
 // LoadModFile sets Target and, if there is a main module, parses the initial
 // build list from its go.mod file.
 //
@@ -539,9 +541,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/libgo/go/cmd/go/internal/modload/list.go b/libgo/go/cmd/go/internal/modload/list.go
index 3491f941cd3..7b1aa7fd413 100644
--- a/libgo/go/cmd/go/internal/modload/list.go
+++ b/libgo/go/cmd/go/internal/modload/list.go
@@ -73,7 +73,7 @@  func listModules(ctx context.Context, args []string, listVersions, listRetracted
 			base.Fatalf("go: cannot use relative path %s to specify module", arg)
 		}
 		if !HasModRoot() && (arg == "all" || strings.Contains(arg, "...")) {
-			base.Fatalf("go: cannot match %q: working directory is not part of a module", arg)
+			base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
 		}
 		if i := strings.Index(arg, "@"); i >= 0 {
 			path := arg[:i]
diff --git a/libgo/go/cmd/go/internal/modload/load.go b/libgo/go/cmd/go/internal/modload/load.go
index 6d87acc6d3b..154fc3c6f0a 100644
--- a/libgo/go/cmd/go/internal/modload/load.go
+++ b/libgo/go/cmd/go/internal/modload/load.go
@@ -170,6 +170,12 @@  type PackageOpts struct {
 	// that occur while loading packages. SilenceErrors implies AllowErrors.
 	SilenceErrors bool
 
+	// SilenceMissingStdImports indicates that LoadPackages should not print
+	// errors or terminate the process if an imported package is missing, and the
+	// import path looks like it might be in the standard library (perhaps in a
+	// future version).
+	SilenceMissingStdImports bool
+
 	// SilenceUnmatchedWarnings suppresses the warnings normally emitted for
 	// patterns that did not match any packages.
 	SilenceUnmatchedWarnings bool
@@ -287,8 +293,13 @@  func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
 					sumErr.importerIsTest = importer.testOf != nil
 				}
 			}
+			silence := opts.SilenceErrors
+			if stdErr := (*ImportMissingError)(nil); errors.As(pkg.err, &stdErr) &&
+				stdErr.isStd && opts.SilenceMissingStdImports {
+				silence = true
+			}
 
-			if !opts.SilenceErrors {
+			if !silence {
 				if opts.AllowErrors {
 					fmt.Fprintf(os.Stderr, "%s: %v\n", pkg.stackText(), pkg.err)
 				} else {
diff --git a/libgo/go/cmd/go/internal/run/run.go b/libgo/go/cmd/go/internal/run/run.go
index 99578b244c8..666b1a0e560 100644
--- a/libgo/go/cmd/go/internal/run/run.go
+++ b/libgo/go/cmd/go/internal/run/run.go
@@ -96,28 +96,12 @@  func runRun(ctx context.Context, cmd *base.Command, args []string) {
 		base.Fatalf("go run: no go files listed")
 	}
 	cmdArgs := args[i:]
-	if p.Error != nil {
-		base.Fatalf("%s", p.Error)
-	}
+	load.CheckPackageErrors([]*load.Package{p})
 
-	p.Internal.OmitDebug = true
-	if len(p.DepsErrors) > 0 {
-		// Since these are errors in dependencies,
-		// the same error might show up multiple times,
-		// once in each package that depends on it.
-		// Only print each once.
-		printed := map[*load.PackageError]bool{}
-		for _, err := range p.DepsErrors {
-			if !printed[err] {
-				printed[err] = true
-				base.Errorf("%s", err)
-			}
-		}
-	}
-	base.ExitIfErrors()
 	if p.Name != "main" {
 		base.Fatalf("go run: cannot run non-main package")
 	}
+	p.Internal.OmitDebug = true
 	p.Target = "" // must build - not up to date
 	if p.Internal.CmdlineFiles {
 		//set executable name if go file is given as cmd-argument
diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt b/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt
index ad22aca5be8..875a836fd27 100644
--- a/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt
@@ -18,7 +18,7 @@  stdout '^m$'
 # Test that we ignore directories when trying to find alternate config files.
 cd $WORK/gopkgdir/x
 ! go list .
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! stderr 'Gopkg.lock'
 
 -- $WORK/test/Gopkg.lock --
diff --git a/libgo/go/cmd/go/testdata/script/mod_edit.txt b/libgo/go/cmd/go/testdata/script/mod_edit.txt
index d7e681e8313..9da69306dac 100644
--- a/libgo/go/cmd/go/testdata/script/mod_edit.txt
+++ b/libgo/go/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/libgo/go/cmd/go/testdata/script/mod_find.txt b/libgo/go/cmd/go/testdata/script/mod_find.txt
index 9468acfd33d..1e01973ff41 100644
--- a/libgo/go/cmd/go/testdata/script/mod_find.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_find.txt
@@ -49,7 +49,7 @@  rm go.mod
 # Test that we ignore directories when trying to find go.mod.
 cd $WORK/gomoddir
 ! go list .
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 [!symlink] stop
 
diff --git a/libgo/go/cmd/go/testdata/script/mod_outside.txt b/libgo/go/cmd/go/testdata/script/mod_outside.txt
index 8f01b5d2426..565589268ee 100644
--- a/libgo/go/cmd/go/testdata/script/mod_outside.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_outside.txt
@@ -12,13 +12,13 @@  stdout 'NUL|/dev/null'
 # 'go list' without arguments implicitly operates on the current directory,
 # which is not in a module.
 ! go list
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 go list -m
 stdout '^command-line-arguments$'
 # 'go list' in the working directory should fail even if there is a a 'package
 # main' present: without a main module, we do not know its package path.
 ! go list ./needmod
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go list all' lists the transitive import graph of the main module,
 # which is empty if there is no main module.
@@ -41,7 +41,7 @@  stdout 'command-line-arguments'
 
 # 'go list' on a package from a module should fail.
 ! go list example.com/printversion
-stderr '^no required module provides package example.com/printversion: working directory is not part of a module$'
+stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 
 # 'go list -m' with an explicit version should resolve that version.
@@ -54,19 +54,19 @@  stdout 'v1.0.0\s+v1.0.1\s+v1.1.0'
 
 # 'go list -m all' should fail. "all" is not meaningful outside of a module.
 ! go list -m all
-stderr 'go: cannot match "all": working directory is not part of a module'
+stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go list -m <mods> all' should also fail.
 ! go list -m example.com/printversion@v1.0.0 all
-stderr 'go: cannot match "all": working directory is not part of a module'
+stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! stdout 'example.com/version'
 
 # 'go list -m' with wildcards should fail. Wildcards match modules in the
 # build list, so they aren't meaningful outside a module.
 ! go list -m ...
-stderr 'go: cannot match "...": working directory is not part of a module'
+stderr 'go: cannot match "...": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! go list -m rsc.io/quote/...
-stderr 'go: cannot match "rsc.io/quote/...": working directory is not part of a module'
+stderr 'go: cannot match "rsc.io/quote/...": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 
 # 'go clean' should skip the current directory if it isn't in a module.
@@ -76,20 +76,20 @@  go clean -n
 
 # 'go mod graph' should fail, since there's no module graph.
 ! go mod graph
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go mod why' should fail, since there is no main module to depend on anything.
 ! go mod why -m example.com/version
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go mod edit', 'go mod tidy', and 'go mod fmt' should fail:
 # there is no go.mod file to edit.
 ! go mod tidy
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! go mod edit -fmt
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! go mod edit -require example.com/version@v1.0.0
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 
 # 'go mod download' without arguments should report an error.
@@ -104,33 +104,33 @@  exists $GOPATH/pkg/mod/cache/download/example.com/printversion/@v/v1.0.0.zip
 
 # 'go mod download all' should fail. "all" is not meaningful outside of a module.
 ! go mod download all
-stderr 'go: cannot match "all": working directory is not part of a module'
+stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 
 # 'go mod vendor' should fail: it starts by clearing the existing vendor
 # directory, and we don't know where that is.
 ! go mod vendor
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 
 # 'go mod verify' should fail: we have no modules to verify.
 ! go mod verify
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 
 # 'go get' without arguments implicitly operates on the main module, and thus
 # should fail.
 ! go get
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! go get -u
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! go get -u ./needmod
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go get -u all' upgrades the transitive import graph of the main module,
 # which is empty.
 ! go get -u all
-stderr 'go get: cannot match "all": working directory is not part of a module'
+stderr '^go get: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go get' should check the proposed module graph for consistency,
 # even though we won't write it anywhere.
@@ -147,16 +147,16 @@  exists $GOPATH/pkg/mod/example.com/version@v1.0.0
 # 'go build' without arguments implicitly operates on the current directory, and should fail.
 cd needmod
 ! go build
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 cd ..
 
 # 'go build' of a non-module directory should fail too.
 ! go build ./needmod
-stderr 'cannot find main module'
+stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go build' of source files should fail if they import anything outside std.
 ! go build -n ./needmod/needmod.go
-stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module$'
+stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go build' of source files should succeed if they do not import anything outside std.
 go build -n -o ignore ./stdonly/stdonly.go
@@ -179,7 +179,7 @@  go doc fmt
 
 # 'go doc' should fail for a package path outside a module.
 ! go doc example.com/version
-stderr 'doc: no required module provides package example.com/version: working directory is not part of a module'
+stderr 'doc: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go install' with a version should succeed if all constraints are met.
 # See mod_install_pkg_version.
@@ -194,7 +194,7 @@  stderr '^go install: version is required when current directory is not in a modu
 # 'go install' should fail if a source file imports a package that must be
 # resolved to a module.
 ! go install ./needmod/needmod.go
-stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module'
+stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go install' should succeed with a package in GOROOT.
 go install cmd/addr2line
@@ -206,12 +206,12 @@  stderr 'can only use path@version syntax with'
 
 # 'go run' should fail if a package argument must be resolved to a module.
 ! go run example.com/printversion
-stderr '^no required module provides package example.com/printversion: working directory is not part of a module$'
+stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 # 'go run' should fail if a source file imports a package that must be
 # resolved to a module.
 ! go run ./needmod/needmod.go
-stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module$'
+stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 
 
 # 'go fmt' should be able to format files outside of a module.
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_error.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_error.txt
index b6c24ceaf75..395537b1a71 100644
--- a/libgo/go/cmd/go/testdata/script/mod_tidy_error.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_tidy_error.txt
@@ -4,12 +4,12 @@  env GO111MODULE=on
 # 'go mod tidy' and 'go mod vendor' should not hide loading errors.
 
 ! go mod tidy
-stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)'
+! stderr 'package nonexist is not in GOROOT'
 stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
 stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
 
 ! go mod vendor
-stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)'
+! stderr 'package nonexist is not in GOROOT'
 stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
 stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
 
diff --git a/libgo/go/cmd/vendor/modules.txt b/libgo/go/cmd/vendor/modules.txt
index e033984956b..10842768a88 100644
--- a/libgo/go/cmd/vendor/modules.txt
+++ b/libgo/go/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/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go
index adaf4daf198..6f9594d7ba7 100644
--- a/libgo/go/encoding/xml/xml.go
+++ b/libgo/go/encoding/xml/xml.go
@@ -271,7 +271,7 @@  func NewTokenDecoder(t TokenReader) *Decoder {
 // it will return an error.
 //
 // Token implements XML name spaces as described by
-// https://www.w3.org/TR/REC-xml-names/.  Each of the
+// https://www.w3.org/TR/REC-xml-names/. Each of the
 // Name structures contained in the Token has the Space
 // set to the URL identifying its name space when known.
 // If Token encounters an unrecognized name space prefix,
@@ -285,16 +285,17 @@  func (d *Decoder) Token() (Token, error) {
 	if d.nextToken != nil {
 		t = d.nextToken
 		d.nextToken = nil
-	} else if t, err = d.rawToken(); err != nil {
-		switch {
-		case err == io.EOF && d.t != nil:
-			err = nil
-		case err == io.EOF && d.stk != nil && d.stk.kind != stkEOF:
-			err = d.syntaxError("unexpected EOF")
+	} else {
+		if t, err = d.rawToken(); t == nil && err != nil {
+			if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
+				err = d.syntaxError("unexpected EOF")
+			}
+			return nil, err
 		}
-		return t, err
+		// We still have a token to process, so clear any
+		// errors (e.g. EOF) and proceed.
+		err = nil
 	}
-
 	if !d.Strict {
 		if t1, ok := d.autoClose(t); ok {
 			d.nextToken = t
diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go
index efddca43e91..5672ebb375f 100644
--- a/libgo/go/encoding/xml/xml_test.go
+++ b/libgo/go/encoding/xml/xml_test.go
@@ -33,30 +33,90 @@  func (t *toks) Token() (Token, error) {
 
 func TestDecodeEOF(t *testing.T) {
 	start := StartElement{Name: Name{Local: "test"}}
-	t.Run("EarlyEOF", func(t *testing.T) {
-		d := NewTokenDecoder(&toks{earlyEOF: true, t: []Token{
-			start,
-			start.End(),
-		}})
-		err := d.Decode(&struct {
-			XMLName Name `xml:"test"`
-		}{})
-		if err != nil {
-			t.Error(err)
+	tests := []struct {
+		name   string
+		tokens []Token
+		ok     bool
+	}{
+		{
+			name: "OK",
+			tokens: []Token{
+				start,
+				start.End(),
+			},
+			ok: true,
+		},
+		{
+			name: "Malformed",
+			tokens: []Token{
+				start,
+				StartElement{Name: Name{Local: "bad"}},
+				start.End(),
+			},
+			ok: false,
+		},
+	}
+	for _, tc := range tests {
+		for _, eof := range []bool{true, false} {
+			name := fmt.Sprintf("%s/earlyEOF=%v", tc.name, eof)
+			t.Run(name, func(t *testing.T) {
+				d := NewTokenDecoder(&toks{
+					earlyEOF: eof,
+					t:        tc.tokens,
+				})
+				err := d.Decode(&struct {
+					XMLName Name `xml:"test"`
+				}{})
+				if tc.ok && err != nil {
+					t.Fatalf("d.Decode: expected nil error, got %v", err)
+				}
+				if _, ok := err.(*SyntaxError); !tc.ok && !ok {
+					t.Errorf("d.Decode: expected syntax error, got %v", err)
+				}
+			})
 		}
-	})
-	t.Run("LateEOF", func(t *testing.T) {
-		d := NewTokenDecoder(&toks{t: []Token{
-			start,
-			start.End(),
-		}})
-		err := d.Decode(&struct {
-			XMLName Name `xml:"test"`
-		}{})
-		if err != nil {
-			t.Error(err)
+	}
+}
+
+type toksNil struct {
+	returnEOF bool
+	t         []Token
+}
+
+func (t *toksNil) Token() (Token, error) {
+	if len(t.t) == 0 {
+		if !t.returnEOF {
+			// Return nil, nil before returning an EOF. It's legal, but
+			// discouraged.
+			t.returnEOF = true
+			return nil, nil
 		}
-	})
+		return nil, io.EOF
+	}
+	var tok Token
+	tok, t.t = t.t[0], t.t[1:]
+	return tok, nil
+}
+
+func TestDecodeNilToken(t *testing.T) {
+	for _, strict := range []bool{true, false} {
+		name := fmt.Sprintf("Strict=%v", strict)
+		t.Run(name, func(t *testing.T) {
+			start := StartElement{Name: Name{Local: "test"}}
+			bad := StartElement{Name: Name{Local: "bad"}}
+			d := NewTokenDecoder(&toksNil{
+				// Malformed
+				t: []Token{start, bad, start.End()},
+			})
+			d.Strict = strict
+			err := d.Decode(&struct {
+				XMLName Name `xml:"test"`
+			}{})
+			if _, ok := err.(*SyntaxError); !ok {
+				t.Errorf("d.Decode: expected syntax error, got %v", err)
+			}
+		})
+	}
 }
 
 const testInput = `
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index 490c212642c..1c0dc4692c9 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -614,7 +614,7 @@  func TestImportPackageOutsideModule(t *testing.T) {
 	ctxt.GOPATH = gopath
 	ctxt.Dir = filepath.Join(gopath, "src/example.com/p")
 
-	want := "working directory is not part of a module"
+	want := "go.mod file not found in current directory or any parent directory"
 	if _, err := ctxt.Import("example.com/p", gopath, FindOnly); err == nil {
 		t.Fatal("importing package when no go.mod is present succeeded unexpectedly")
 	} else if errStr := err.Error(); !strings.Contains(errStr, want) {
diff --git a/libgo/go/golang.org/x/mod/modfile/rule.go b/libgo/go/golang.org/x/mod/modfile/rule.go
index c6a189dbe04..f8c93849859 100644
--- a/libgo/go/golang.org/x/mod/modfile/rule.go
+++ b/libgo/go/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/libgo/go/golang.org/x/mod/module/module.go b/libgo/go/golang.org/x/mod/module/module.go
index c1c5263c427..272baeef176 100644
--- a/libgo/go/golang.org/x/mod/module/module.go
+++ b/libgo/go/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/libgo/go/time/zoneinfo.go b/libgo/go/time/zoneinfo.go
index c3662297c7d..6db94434747 100644
--- a/libgo/go/time/zoneinfo.go
+++ b/libgo/go/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/libgo/go/time/zoneinfo_test.go b/libgo/go/time/zoneinfo_test.go
index d543f93e3b7..3e32da02b2e 100644
--- a/libgo/go/time/zoneinfo_test.go
+++ b/libgo/go/time/zoneinfo_test.go
@@ -189,22 +189,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)
+		}
 	}
 }
 
@@ -269,7 +297,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)
@@ -294,6 +323,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/libgo/misc/cgo/testplugin/plugin_test.go b/libgo/misc/cgo/testplugin/plugin_test.go
index 9055dbda044..2d991012c82 100644
--- a/libgo/misc/cgo/testplugin/plugin_test.go
+++ b/libgo/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/libgo/misc/cgo/testplugin/testdata/method2/main.go b/libgo/misc/cgo/testplugin/testdata/method2/main.go
new file mode 100644
index 00000000000..6a87e7b6a0f
--- /dev/null
+++ b/libgo/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/libgo/misc/cgo/testplugin/testdata/method2/p/p.go b/libgo/misc/cgo/testplugin/testdata/method2/p/p.go
new file mode 100644
index 00000000000..acb526acec9
--- /dev/null
+++ b/libgo/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/libgo/misc/cgo/testplugin/testdata/method2/plugin.go b/libgo/misc/cgo/testplugin/testdata/method2/plugin.go
new file mode 100644
index 00000000000..6198e7648ee
--- /dev/null
+++ b/libgo/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 }