From 87cbbc45a950f382853e2e4cf494cdfab62f0e5b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 11 Jun 2018 19:16:34 +0000 Subject: libgo: add riscv and js/wasm as known targets Incorporates cut down versions of https://golang.org/cl/102835 and https://golang.org/cl/106256 from the master sources. This will tell go/build to skip files with those tags. Reviewed-on: https://go-review.googlesource.com/117996 From-SVN: r261451 --- libgo/configure | 4 ++-- libgo/configure.ac | 4 ++-- libgo/go/go/build/syslist.go | 4 ++-- libgo/go/go/types/sizes.go | 3 ++- libgo/goarch.sh | 9 +++++++++ 5 files changed, 17 insertions(+), 7 deletions(-) (limited to 'libgo') diff --git a/libgo/configure b/libgo/configure index 11e04aa..66942ed 100755 --- a/libgo/configure +++ b/libgo/configure @@ -13653,10 +13653,10 @@ esac # - libgo/go/syscall/endian_XX.go # - possibly others # - possibly update files in libgo/go/internal/syscall/unix -ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc ppc64 ppc64le riscv64 s390 s390x sh shbe sparc sparc64" +ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc ppc64 ppc64le riscv riscv64 s390 s390x sh shbe sparc sparc64 wasm" # All known GOARCH family values. -ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 NIOS2 PPC PPC64 RISCV64 S390 S390X SH SPARC SPARC64" +ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 NIOS2 PPC PPC64 RISCV RISCV64 S390 S390X SH SPARC SPARC64 WASM" GOARCH=unknown case ${host} in diff --git a/libgo/configure.ac b/libgo/configure.ac index 9f4bf50..3cee2c0 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -224,10 +224,10 @@ AC_SUBST(USE_DEJAGNU) # - libgo/go/syscall/endian_XX.go # - possibly others # - possibly update files in libgo/go/internal/syscall/unix -ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc ppc64 ppc64le riscv64 s390 s390x sh shbe sparc sparc64" +ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc ppc64 ppc64le riscv riscv64 s390 s390x sh shbe sparc sparc64 wasm" # All known GOARCH family values. -ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 NIOS2 PPC PPC64 RISCV64 S390 S390X SH SPARC SPARC64" +ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 NIOS2 PPC PPC64 RISCV RISCV64 S390 S390X SH SPARC SPARC64 WASM" GOARCH=unknown case ${host} in diff --git a/libgo/go/go/build/syslist.go b/libgo/go/go/build/syslist.go index 0c39634..baa9572 100644 --- a/libgo/go/go/build/syslist.go +++ b/libgo/go/go/build/syslist.go @@ -4,5 +4,5 @@ package build -const goosList = "aix android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows zos " -const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be alpha m68k ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc riscv64 s390 s390x sh shbe sparc sparc64" +const goosList = "aix android darwin dragonfly freebsd js linux nacl netbsd openbsd plan9 solaris windows zos " +const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be alpha m68k ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc riscv riscv64 s390 s390x sh shbe sparc sparc64 wasm " diff --git a/libgo/go/go/types/sizes.go b/libgo/go/go/types/sizes.go index 05d14da..13e2abb 100644 --- a/libgo/go/go/types/sizes.go +++ b/libgo/go/go/types/sizes.go @@ -167,6 +167,7 @@ var gcArchSizes = map[string]*StdSizes{ "ppc64": {8, 8}, "ppc64le": {8, 8}, "s390x": {8, 8}, + "wasm": {8, 8}, // When adding more architectures here, // update the doc string of SizesFor below. } @@ -176,7 +177,7 @@ var gcArchSizes = map[string]*StdSizes{ // // Supported architectures for compiler "gc": // "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle", -// "mips64", "mips64le", "ppc64", "ppc64le", "s390x". +// "mips64", "mips64le", "ppc64", "ppc64le", "s390x", "wasm". func SizesFor(compiler, arch string) Sizes { var m map[string]*StdSizes switch compiler { diff --git a/libgo/goarch.sh b/libgo/goarch.sh index 11bca7b..f5c0a34 100755 --- a/libgo/goarch.sh +++ b/libgo/goarch.sh @@ -153,6 +153,11 @@ case $goarch in ;; esac ;; + riscv) + family=RISCV + pcquantum=2 + ptrsize=4 + ;; riscv64) family=RISCV64 pcquantum=2 @@ -198,6 +203,10 @@ case $goarch in defaultphyspagesize=8192 pcquantum=4 ;; + wasm) + family=WASM + defaultphyspagesize=65536 + ;; *) echo 1>&2 "unrecognized goarch value \"$goarch\"" exit 1 -- cgit v1.1 From c9492649182de9b36eaa71a49b96143e551afc54 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 13 Jun 2018 13:51:23 +0000 Subject: libgo: update to Go 1.10.3 release Reviewed-on: https://go-review.googlesource.com/118495 From-SVN: r261549 --- libgo/MERGE | 2 +- libgo/VERSION | 2 +- libgo/go/cmd/go/internal/get/discovery.go | 7 + libgo/go/cmd/go/internal/get/get.go | 10 +- libgo/go/cmd/go/internal/get/pkg_test.go | 14 + libgo/go/cmd/go/internal/list/list.go | 4 +- libgo/go/cmd/go/internal/load/icfg.go | 78 ------ libgo/go/cmd/go/internal/load/pkg.go | 294 ++++++++++++++++----- libgo/go/cmd/go/internal/test/test.go | 4 +- libgo/go/cmd/go/internal/work/build.go | 1 - libgo/go/cmd/go/internal/work/security.go | 37 ++- libgo/go/cmd/go/internal/work/security_test.go | 5 + libgo/go/cmd/go/testdata/modlegacy/src/new/go.mod | 1 + libgo/go/cmd/go/testdata/modlegacy/src/new/new.go | 3 + .../go/cmd/go/testdata/modlegacy/src/new/p1/p1.go | 7 + .../go/cmd/go/testdata/modlegacy/src/new/p2/p2.go | 1 + .../cmd/go/testdata/modlegacy/src/new/sub/go.mod | 1 + .../go/testdata/modlegacy/src/new/sub/inner/go.mod | 1 + .../go/testdata/modlegacy/src/new/sub/inner/x/x.go | 1 + .../go/testdata/modlegacy/src/new/sub/x/v1/y/y.go | 1 + .../go/cmd/go/testdata/modlegacy/src/old/p1/p1.go | 5 + .../go/cmd/go/testdata/modlegacy/src/old/p2/p2.go | 1 + libgo/go/cmd/go/vendor_test.go | 73 +++++ libgo/go/crypto/x509/name_constraints_test.go | 46 +++- libgo/go/crypto/x509/root_windows.go | 12 +- libgo/go/crypto/x509/verify.go | 237 ++++++----------- libgo/go/strings/strings.go | 4 +- libgo/go/strings/strings_test.go | 23 ++ libgo/misc/cgo/testcshared/main2.c | 2 +- libgo/misc/cgo/testcshared/src/libgo2/libgo2.go | 2 +- 30 files changed, 552 insertions(+), 327 deletions(-) delete mode 100644 libgo/go/cmd/go/internal/load/icfg.go create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/go.mod create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/new.go create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/p1/p1.go create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/p2/p2.go create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/sub/go.mod create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/old/p1/p1.go create mode 100644 libgo/go/cmd/go/testdata/modlegacy/src/old/p2/p2.go (limited to 'libgo') diff --git a/libgo/MERGE b/libgo/MERGE index 6f31fab..c54da0d 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -71bdbf431b79dff61944f22c25c7e085ccfc25d5 +fe8a0d12b14108cbe2408b417afcaab722b0727c 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 98736c7..038f0b9 100644 --- a/libgo/VERSION +++ b/libgo/VERSION @@ -1 +1 @@ -go1.10.2 +go1.10.3 diff --git a/libgo/go/cmd/go/internal/get/discovery.go b/libgo/go/cmd/go/internal/get/discovery.go index b2918db..97aa1d7 100644 --- a/libgo/go/cmd/go/internal/get/discovery.go +++ b/libgo/go/cmd/go/internal/get/discovery.go @@ -55,6 +55,13 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { continue } if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { + // Ignore VCS type "mod", which is new Go modules. + // This code is for old go get and must ignore the new mod lines. + // Otherwise matchGoImport will complain about two + // different metaImport lines for the same Prefix. + if f[1] == "mod" { + continue + } imports = append(imports, metaImport{ Prefix: f[0], VCS: f[1], diff --git a/libgo/go/cmd/go/internal/get/get.go b/libgo/go/cmd/go/internal/get/get.go index 733116e..5bfeac3 100644 --- a/libgo/go/cmd/go/internal/get/get.go +++ b/libgo/go/cmd/go/internal/get/get.go @@ -209,7 +209,7 @@ var downloadRootCache = map[string]bool{} // download runs the download half of the get command // for the package named by the argument. func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) { - if mode&load.UseVendor != 0 { + if mode&load.ResolveImport != 0 { // Caller is responsible for expanding vendor paths. panic("internal error: download mode has useVendor set") } @@ -217,7 +217,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) if parent == nil { return load.LoadPackage(path, stk) } - return load.LoadImport(path, parent.Dir, parent, stk, nil, mode) + return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule) } p := load1(arg, mode) @@ -346,12 +346,12 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) base.Errorf("%s", err) continue } - // If this is a test import, apply vendor lookup now. - // We cannot pass useVendor to download, because + // If this is a test import, apply module and vendor lookup now. + // We cannot pass ResolveImport to download, because // download does caching based on the value of path, // so it must be the fully qualified path already. if i >= len(p.Imports) { - path = load.VendoredImportPath(p, path) + path = load.ResolveImportPath(p, path) } download(path, p, stk, 0) } diff --git a/libgo/go/cmd/go/internal/get/pkg_test.go b/libgo/go/cmd/go/internal/get/pkg_test.go index b8937a5..1179d86 100644 --- a/libgo/go/cmd/go/internal/get/pkg_test.go +++ b/libgo/go/cmd/go/internal/get/pkg_test.go @@ -48,6 +48,20 @@ var parseMetaGoImportsTests = []struct { }, }, { + ` + `, + []metaImport{ + {"foo/bar", "git", "https://github.com/rsc/foo/bar"}, + }, + }, + { + ` + `, + []metaImport{ + {"foo/bar", "git", "https://github.com/rsc/foo/bar"}, + }, + }, + { ` `, diff --git a/libgo/go/cmd/go/internal/list/list.go b/libgo/go/cmd/go/internal/list/list.go index 7435273..16e7f70 100644 --- a/libgo/go/cmd/go/internal/list/list.go +++ b/libgo/go/cmd/go/internal/list/list.go @@ -218,8 +218,8 @@ func runList(cmd *base.Command, args []string) { for _, pkg := range pkgs { // Show vendor-expanded paths in listing - pkg.TestImports = pkg.Vendored(pkg.TestImports) - pkg.XTestImports = pkg.Vendored(pkg.XTestImports) + pkg.TestImports = pkg.Resolve(pkg.TestImports) + pkg.XTestImports = pkg.Resolve(pkg.XTestImports) do(&pkg.PackagePublic) } diff --git a/libgo/go/cmd/go/internal/load/icfg.go b/libgo/go/cmd/go/internal/load/icfg.go deleted file mode 100644 index d8dd664..0000000 --- a/libgo/go/cmd/go/internal/load/icfg.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2017 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 load - -import ( - "bytes" - "encoding/json" - "errors" - "io/ioutil" -) - -// DebugDeprecatedImportcfg is installed as the undocumented -debug-deprecated-importcfg build flag. -// It is useful for debugging subtle problems in the go command logic but not something -// we want users to depend on. The hope is that the "deprecated" will make that clear. -// We intend to remove this flag in Go 1.11. -var DebugDeprecatedImportcfg debugDeprecatedImportcfgFlag - -type debugDeprecatedImportcfgFlag struct { - enabled bool - Import map[string]string - Pkg map[string]*debugDeprecatedImportcfgPkg -} - -type debugDeprecatedImportcfgPkg struct { - Dir string - Import map[string]string -} - -var ( - debugDeprecatedImportcfgMagic = []byte("# debug-deprecated-importcfg\n") - errImportcfgSyntax = errors.New("malformed syntax") -) - -func (f *debugDeprecatedImportcfgFlag) String() string { return "" } - -func (f *debugDeprecatedImportcfgFlag) Set(x string) error { - if x == "" { - *f = debugDeprecatedImportcfgFlag{} - return nil - } - data, err := ioutil.ReadFile(x) - if err != nil { - return err - } - - if !bytes.HasPrefix(data, debugDeprecatedImportcfgMagic) { - return errImportcfgSyntax - } - data = data[len(debugDeprecatedImportcfgMagic):] - - f.Import = nil - f.Pkg = nil - if err := json.Unmarshal(data, &f); err != nil { - return errImportcfgSyntax - } - f.enabled = true - return nil -} - -func (f *debugDeprecatedImportcfgFlag) lookup(parent *Package, path string) (dir, newPath string) { - newPath = path - if p := f.Import[path]; p != "" { - newPath = p - } - if parent != nil { - if p1 := f.Pkg[parent.ImportPath]; p1 != nil { - if p := p1.Import[path]; p != "" { - newPath = p - } - } - } - if p2 := f.Pkg[newPath]; p2 != nil { - return p2.Dir, newPath - } - return "", "" -} diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go index 882b86d..dfb1ff6 100644 --- a/libgo/go/cmd/go/internal/load/pkg.go +++ b/libgo/go/cmd/go/internal/load/pkg.go @@ -6,6 +6,7 @@ package load import ( + "bytes" "fmt" "go/build" "go/token" @@ -14,6 +15,7 @@ import ( pathpkg "path" "path/filepath" "sort" + "strconv" "strings" "unicode" "unicode/utf8" @@ -168,7 +170,7 @@ func (e *NoGoError) Error() string { return "no Go files in " + e.Package.Dir } -// Vendored returns the vendor-resolved version of imports, +// Resolve returns the resolved version of imports, // which should be p.TestImports or p.XTestImports, NOT p.Imports. // The imports in p.TestImports and p.XTestImports are not recursively // loaded during the initial load of p, so they list the imports found in @@ -178,14 +180,14 @@ func (e *NoGoError) Error() string { // can produce better error messages if it starts with the original paths. // The initial load of p loads all the non-test imports and rewrites // the vendored paths, so nothing should ever call p.vendored(p.Imports). -func (p *Package) Vendored(imports []string) []string { +func (p *Package) Resolve(imports []string) []string { if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] { - panic("internal error: p.vendored(p.Imports) called") + panic("internal error: p.Resolve(p.Imports) called") } seen := make(map[string]bool) var all []string for _, path := range imports { - path = VendoredImportPath(p, path) + path = ResolveImportPath(p, path) if !seen[path] { seen[path] = true all = append(all, path) @@ -380,16 +382,20 @@ func makeImportValid(r rune) rune { // Mode flags for loadImport and download (in get.go). const ( - // UseVendor means that loadImport should do vendor expansion - // (provided the vendoring experiment is enabled). - // That is, useVendor means that the import path came from - // a source file and has not been vendor-expanded yet. - // Every import path should be loaded initially with useVendor, - // and then the expanded version (with the /vendor/ in it) gets - // recorded as the canonical import path. At that point, future loads - // of that package must not pass useVendor, because + // ResolveImport means that loadImport should do import path expansion. + // That is, ResolveImport means that the import path came from + // a source file and has not been expanded yet to account for + // vendoring or possible module adjustment. + // Every import path should be loaded initially with ResolveImport, + // and then the expanded version (for example with the /vendor/ in it) + // gets recorded as the canonical import path. At that point, future loads + // of that package must not pass ResolveImport, because // disallowVendor will reject direct use of paths containing /vendor/. - UseVendor = 1 << iota + ResolveImport = 1 << iota + + // ResolveModule is for download (part of "go get") and indicates + // that the module adjustment should be done, but not vendor adjustment. + ResolveModule // GetTestDeps is for download (part of "go get") and indicates // that test dependencies should be fetched too. @@ -412,20 +418,17 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo importPath := path origPath := path isLocal := build.IsLocalImport(path) - var debugDeprecatedImportcfgDir string if isLocal { importPath = dirToImportPath(filepath.Join(srcDir, path)) - } else if DebugDeprecatedImportcfg.enabled { - if d, i := DebugDeprecatedImportcfg.lookup(parent, path); d != "" { - debugDeprecatedImportcfgDir = d - importPath = i - } - } else if mode&UseVendor != 0 { - // We do our own vendor resolution, because we want to + } else if mode&ResolveImport != 0 { + // We do our own path resolution, because we want to // find out the key to use in packageCache without the // overhead of repeated calls to buildContext.Import. // The code is also needed in a few other places anyway. - path = VendoredImportPath(parent, path) + path = ResolveImportPath(parent, path) + importPath = path + } else if mode&ResolveModule != 0 { + path = ModuleImportPath(parent, path) importPath = path } @@ -441,26 +444,17 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo // Load package. // Import always returns bp != nil, even if an error occurs, // in order to return partial information. - var bp *build.Package - var err error - if debugDeprecatedImportcfgDir != "" { - bp, err = cfg.BuildContext.ImportDir(debugDeprecatedImportcfgDir, 0) - } else if DebugDeprecatedImportcfg.enabled { - bp = new(build.Package) - err = fmt.Errorf("unknown import path %q: not in import cfg", importPath) - } else { - buildMode := build.ImportComment - if mode&UseVendor == 0 || path != origPath { - // Not vendoring, or we already found the vendored path. - buildMode |= build.IgnoreVendor - } - bp, err = cfg.BuildContext.Import(path, srcDir, buildMode) + buildMode := build.ImportComment + if mode&ResolveImport == 0 || path != origPath { + // Not vendoring, or we already found the vendored path. + buildMode |= build.IgnoreVendor } + bp, err := cfg.BuildContext.Import(path, srcDir, buildMode) bp.ImportPath = importPath if cfg.GOBIN != "" { bp.BinDir = cfg.GOBIN } - if debugDeprecatedImportcfgDir == "" && err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path && + if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path && !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") { err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment) } @@ -469,7 +463,7 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo p = setErrorPos(p, importPos) } - if debugDeprecatedImportcfgDir == "" && origPath != cleanImport(origPath) { + if origPath != cleanImport(origPath) { p.Error = &PackageError{ ImportStack: stk.Copy(), Err: fmt.Sprintf("non-canonical import path: %q should be %q", origPath, pathpkg.Clean(origPath)), @@ -482,7 +476,7 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo if perr := disallowInternal(srcDir, p, stk); perr != p { return setErrorPos(perr, importPos) } - if mode&UseVendor != 0 { + if mode&ResolveImport != 0 { if perr := disallowVendor(srcDir, origPath, p, stk); perr != p { return setErrorPos(perr, importPos) } @@ -541,31 +535,31 @@ func isDir(path string) bool { return result } -// VendoredImportPath returns the expansion of path when it appears in parent. -// If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path, -// x/vendor/path, vendor/path, or else stay path if none of those exist. -// VendoredImportPath returns the expanded path or, if no expansion is found, the original. -func VendoredImportPath(parent *Package, path string) (found string) { - if DebugDeprecatedImportcfg.enabled { - if d, i := DebugDeprecatedImportcfg.lookup(parent, path); d != "" { - return i - } - return path - } - - if parent == nil || parent.Root == "" { - return path - } +// ResolveImportPath returns the true meaning of path when it appears in parent. +// There are two different resolutions applied. +// First, there is Go 1.5 vendoring (golang.org/s/go15vendor). +// If vendor expansion doesn't trigger, then the path is also subject to +// Go 1.11 vgo legacy conversion (golang.org/issue/25069). +func ResolveImportPath(parent *Package, path string) (found string) { + found = VendoredImportPath(parent, path) + if found != path { + return found + } + return ModuleImportPath(parent, path) +} - dir := filepath.Clean(parent.Dir) - root := filepath.Join(parent.Root, "src") - if !str.HasFilePathPrefix(dir, root) || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir { +// dirAndRoot returns the source directory and workspace root +// for the package p, guaranteeing that root is a path prefix of dir. +func dirAndRoot(p *Package) (dir, root string) { + dir = filepath.Clean(p.Dir) + root = filepath.Join(p.Root, "src") + if !str.HasFilePathPrefix(dir, root) || p.ImportPath != "command-line-arguments" && filepath.Join(root, p.ImportPath) != dir { // Look for symlinks before reporting error. dir = expandPath(dir) root = expandPath(root) } - if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.Internal.Local && filepath.Join(root, parent.ImportPath) != dir { + if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || p.ImportPath != "command-line-arguments" && !p.Internal.Local && filepath.Join(root, p.ImportPath) != dir { base.Fatalf("unexpected directory layout:\n"+ " import path: %s\n"+ " root: %s\n"+ @@ -573,14 +567,28 @@ func VendoredImportPath(parent *Package, path string) (found string) { " expand root: %s\n"+ " expand dir: %s\n"+ " separator: %s", - parent.ImportPath, - filepath.Join(parent.Root, "src"), - filepath.Clean(parent.Dir), + p.ImportPath, + filepath.Join(p.Root, "src"), + filepath.Clean(p.Dir), root, dir, string(filepath.Separator)) } + return dir, root +} + +// VendoredImportPath returns the vendor-expansion of path when it appears in parent. +// If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path, +// x/vendor/path, vendor/path, or else stay path if none of those exist. +// VendoredImportPath returns the expanded path or, if no expansion is found, the original. +func VendoredImportPath(parent *Package, path string) (found string) { + if parent == nil || parent.Root == "" { + return path + } + + dir, root := dirAndRoot(parent) + vpath := "vendor/" + path for i := len(dir); i >= len(root); i-- { if i < len(dir) && dir[i] != filepath.Separator { @@ -623,6 +631,164 @@ func VendoredImportPath(parent *Package, path string) (found string) { return path } +var ( + modulePrefix = []byte("\nmodule ") + goModPathCache = make(map[string]string) +) + +// goModPath returns the module path in the go.mod in dir, if any. +func goModPath(dir string) (path string) { + path, ok := goModPathCache[dir] + if ok { + return path + } + defer func() { + goModPathCache[dir] = path + }() + + data, err := ioutil.ReadFile(filepath.Join(dir, "go.mod")) + if err != nil { + return "" + } + var i int + if bytes.HasPrefix(data, modulePrefix[1:]) { + i = 0 + } else { + i = bytes.Index(data, modulePrefix) + if i < 0 { + return "" + } + i++ + } + line := data[i:] + + // Cut line at \n, drop trailing \r if present. + if j := bytes.IndexByte(line, '\n'); j >= 0 { + line = line[:j] + } + if line[len(line)-1] == '\r' { + line = line[:len(line)-1] + } + line = line[len("module "):] + + // If quoted, unquote. + path = strings.TrimSpace(string(line)) + if path != "" && path[0] == '"' { + s, err := strconv.Unquote(path) + if err != nil { + return "" + } + path = s + } + return path +} + +// findVersionElement returns the slice indices of the final version element /vN in path. +// If there is no such element, it returns -1, -1. +func findVersionElement(path string) (i, j int) { + j = len(path) + for i = len(path) - 1; i >= 0; i-- { + if path[i] == '/' { + if isVersionElement(path[i:j]) { + return i, j + } + j = i + } + } + return -1, -1 +} + +// isVersionElement reports whether s is a well-formed path version element: +// v2, v3, v10, etc, but not v0, v05, v1. +func isVersionElement(s string) bool { + if len(s) < 3 || s[0] != '/' || s[1] != 'v' || s[2] == '0' || s[2] == '1' && len(s) == 3 { + return false + } + for i := 2; i < len(s); i++ { + if s[i] < '0' || '9' < s[i] { + return false + } + } + return true +} + +// ModuleImportPath translates import paths found in go modules +// back down to paths that can be resolved in ordinary builds. +// +// Define “new” code as code with a go.mod file in the same directory +// or a parent directory. If an import in new code says x/y/v2/z but +// x/y/v2/z does not exist and x/y/go.mod says “module x/y/v2”, +// then go build will read the import as x/y/z instead. +// See golang.org/issue/25069. +func ModuleImportPath(parent *Package, path string) (found string) { + if parent == nil || parent.Root == "" { + return path + } + + // If there are no vN elements in path, leave it alone. + // (The code below would do the same, but only after + // some other file system accesses that we can avoid + // here by returning early.) + if i, _ := findVersionElement(path); i < 0 { + return path + } + + dir, root := dirAndRoot(parent) + + // Consider dir and parents, up to and including root. + for i := len(dir); i >= len(root); i-- { + if i < len(dir) && dir[i] != filepath.Separator { + continue + } + if goModPath(dir[:i]) != "" { + goto HaveGoMod + } + } + // This code is not in a tree with a go.mod, + // so apply no changes to the path. + return path + +HaveGoMod: + // This import is in a tree with a go.mod. + // Allow it to refer to code in GOPATH/src/x/y/z as x/y/v2/z + // if GOPATH/src/x/y/go.mod says module "x/y/v2", + + // If x/y/v2/z exists, use it unmodified. + if bp, _ := cfg.BuildContext.Import(path, "", build.IgnoreVendor); bp.Dir != "" { + return path + } + + // Otherwise look for a go.mod supplying a version element. + // Some version-like elements may appear in paths but not + // be module versions; we skip over those to look for module + // versions. For example the module m/v2 might have a + // package m/v2/api/v1/foo. + limit := len(path) + for limit > 0 { + i, j := findVersionElement(path[:limit]) + if i < 0 { + return path + } + if bp, _ := cfg.BuildContext.Import(path[:i], "", build.IgnoreVendor); bp.Dir != "" { + if mpath := goModPath(bp.Dir); mpath != "" { + // Found a valid go.mod file, so we're stopping the search. + // If the path is m/v2/p and we found m/go.mod that says + // "module m/v2", then we return "m/p". + if mpath == path[:j] { + return path[:i] + path[j:] + } + // Otherwise just return the original path. + // We didn't find anything worth rewriting, + // and the go.mod indicates that we should + // not consider parent directories. + return path + } + } + limit = i + } + return path +} + // hasGoFiles reports whether dir contains any files with names ending in .go. // For a vendor check we must exclude directories that contain no .go files. // Otherwise it is not possible to vendor just a/b/c and still import the @@ -1087,7 +1253,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { if path == "C" { continue } - p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], UseVendor) + p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport) if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil { p.Error = &PackageError{ ImportStack: stk.Copy(), @@ -1598,7 +1764,7 @@ func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err stk.Push(p.ImportPath + " (test)") rawTestImports := str.StringList(p.TestImports) for i, path := range p.TestImports { - p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], UseVendor) + p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport) if p1.Error != nil { return nil, nil, p1.Error } @@ -1626,7 +1792,7 @@ func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err pxtestNeedsPtest := false rawXTestImports := str.StringList(p.XTestImports) for i, path := range p.XTestImports { - p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], UseVendor) + p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport) if p1.Error != nil { return nil, nil, p1.Error } diff --git a/libgo/go/cmd/go/internal/test/test.go b/libgo/go/cmd/go/internal/test/test.go index 72415cc..5adb7df 100644 --- a/libgo/go/cmd/go/internal/test/test.go +++ b/libgo/go/cmd/go/internal/test/test.go @@ -606,10 +606,10 @@ func runTest(cmd *base.Command, args []string) { for _, path := range p.Imports { deps[path] = true } - for _, path := range p.Vendored(p.TestImports) { + for _, path := range p.Resolve(p.TestImports) { deps[path] = true } - for _, path := range p.Vendored(p.XTestImports) { + for _, path := range p.Resolve(p.XTestImports) { deps[path] = true } } diff --git a/libgo/go/cmd/go/internal/work/build.go b/libgo/go/cmd/go/internal/work/build.go index 57b7b00..25dfe58 100644 --- a/libgo/go/cmd/go/internal/work/build.go +++ b/libgo/go/cmd/go/internal/work/build.go @@ -229,7 +229,6 @@ func AddBuildFlags(cmd *base.Command) { // Undocumented, unstable debugging flags. cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "") - cmd.Flag.Var(&load.DebugDeprecatedImportcfg, "debug-deprecated-importcfg", "") } // fileExtSplit expects a filename and returns the name diff --git a/libgo/go/cmd/go/internal/work/security.go b/libgo/go/cmd/go/internal/work/security.go index 5c67aa9..1b82af9 100644 --- a/libgo/go/cmd/go/internal/work/security.go +++ b/libgo/go/cmd/go/internal/work/security.go @@ -41,43 +41,57 @@ var re = regexp.MustCompile var validCompilerFlags = []*regexp.Regexp{ re(`-D([A-Za-z_].*)`), + re(`-F([^@\-].*)`), re(`-I([^@\-].*)`), re(`-O`), re(`-O([^@\-].*)`), re(`-W`), re(`-W([^@,]+)`), // -Wall but not -Wa,-foo. re(`-Wa,-mbig-obj`), + re(`-Wp,-D([A-Za-z_].*)`), re(`-ansi`), + re(`-f(no-)?asynchronous-unwind-tables`), re(`-f(no-)?blocks`), + re(`-f(no-)builtin-[a-zA-Z0-9_]*`), re(`-f(no-)?common`), re(`-f(no-)?constant-cfstrings`), re(`-fdiagnostics-show-note-include-stack`), + re(`-f(no-)?eliminate-unused-debug-types`), re(`-f(no-)?exceptions`), + re(`-f(no-)?fast-math`), re(`-f(no-)?inline-functions`), re(`-finput-charset=([^@\-].*)`), re(`-f(no-)?fat-lto-objects`), + re(`-f(no-)?keep-inline-dllexport`), re(`-f(no-)?lto`), re(`-fmacro-backtrace-limit=(.+)`), re(`-fmessage-length=(.+)`), re(`-f(no-)?modules`), re(`-f(no-)?objc-arc`), + re(`-f(no-)?objc-nonfragile-abi`), + re(`-f(no-)?objc-legacy-dispatch`), re(`-f(no-)?omit-frame-pointer`), re(`-f(no-)?openmp(-simd)?`), re(`-f(no-)?permissive`), re(`-f(no-)?(pic|PIC|pie|PIE)`), + re(`-f(no-)?plt`), re(`-f(no-)?rtti`), re(`-f(no-)?split-stack`), re(`-f(no-)?stack-(.+)`), re(`-f(no-)?strict-aliasing`), re(`-f(un)signed-char`), re(`-f(no-)?use-linker-plugin`), // safe if -B is not used; we don't permit -B + re(`-f(no-)?visibility-inlines-hidden`), re(`-fsanitize=(.+)`), re(`-ftemplate-depth-(.+)`), re(`-fvisibility=(.+)`), re(`-g([^@\-].*)?`), re(`-m32`), re(`-m64`), - re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-m(abi|arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-marm`), + re(`-mfloat-abi=([^@\-].*)`), + re(`-mfpmath=[0-9a-z,+]*`), re(`-m(no-)?avx[0-9a-z.]*`), re(`-m(no-)?ms-bitfields`), re(`-m(no-)?stack-(.+)`), @@ -86,12 +100,16 @@ var validCompilerFlags = []*regexp.Regexp{ re(`-miphoneos-version-min=(.+)`), re(`-mnop-fun-dllimport`), re(`-m(no-)?sse[0-9.]*`), + re(`-mthumb(-interwork)?`), + re(`-mthreads`), re(`-mwindows`), + re(`--param=ssp-buffer-size=[0-9]*`), re(`-pedantic(-errors)?`), re(`-pipe`), re(`-pthread`), re(`-?-std=([^@\-].*)`), re(`-?-stdlib=([^@\-].*)`), + re(`--sysroot=([^@\-].*)`), re(`-w`), re(`-x([^@\-].*)`), } @@ -115,15 +133,20 @@ var validLinkerFlags = []*regexp.Regexp{ re(`-O`), re(`-O([^@\-].*)`), re(`-f(no-)?(pic|PIC|pie|PIE)`), + re(`-f(no-)?openmp(-simd)?`), re(`-fsanitize=([^@\-].*)`), re(`-g([^@\-].*)?`), - re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-headerpad_max_install_names`), + re(`-m(abi|arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-mfloat-abi=([^@\-].*)`), re(`-mmacosx-(.+)`), re(`-mios-simulator-version-min=(.+)`), re(`-miphoneos-version-min=(.+)`), + re(`-mthreads`), re(`-mwindows`), re(`-(pic|PIC|pie|PIE)`), re(`-pthread`), + re(`-rdynamic`), re(`-shared`), re(`-?-static([-a-z0-9+]*)`), re(`-?-stdlib=([^@\-].*)`), @@ -134,22 +157,27 @@ var validLinkerFlags = []*regexp.Regexp{ // in a wildcard would allow tunnelling arbitrary additional // linker arguments through one of these. re(`-Wl,--(no-)?allow-multiple-definition`), + re(`-Wl,--(no-)?allow-shlib-undefined`), re(`-Wl,--(no-)?as-needed`), re(`-Wl,-Bdynamic`), re(`-Wl,-Bstatic`), + re(`-WL,-O([^@,\-][^,]*)?`), re(`-Wl,-d[ny]`), re(`-Wl,--disable-new-dtags`), + re(`-Wl,-e[=,][a-zA-Z0-9]*`), re(`-Wl,--enable-new-dtags`), re(`-Wl,--end-group`), re(`-Wl,-framework,[^,@\-][^,]+`), re(`-Wl,-headerpad_max_install_names`), re(`-Wl,--no-undefined`), - re(`-Wl,-rpath[=,]([^,@\-][^,]+)`), + re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`), + re(`-Wl,-s`), re(`-Wl,-search_paths_first`), re(`-Wl,-sectcreate,([^,@\-][^,]+),([^,@\-][^,]+),([^,@\-][^,]+)`), re(`-Wl,--start-group`), re(`-Wl,-?-static`), - re(`-Wl,--subsystem,(native|windows|console|posix|xbox)`), + re(`-Wl,-?-subsystem,(native|windows|console|posix|xbox)`), + re(`-Wl,-syslibroot[=,]([^,@\-][^,]+)`), re(`-Wl,-undefined[=,]([^,@\-][^,]+)`), re(`-Wl,-?-unresolved-symbols=[^,]+`), re(`-Wl,--(no-)?warn-([^,]+)`), @@ -157,6 +185,7 @@ var validLinkerFlags = []*regexp.Regexp{ re(`-Wl,-z,relro`), re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o) + re(`\./.*\.(a|o|obj|dll|dylib|so)`), } var validLinkerFlagsWithNextArg = []string{ diff --git a/libgo/go/cmd/go/internal/work/security_test.go b/libgo/go/cmd/go/internal/work/security_test.go index bd898c9..c3a61b8 100644 --- a/libgo/go/cmd/go/internal/work/security_test.go +++ b/libgo/go/cmd/go/internal/work/security_test.go @@ -12,6 +12,7 @@ import ( var goodCompilerFlags = [][]string{ {"-DFOO"}, {"-Dfoo=bar"}, + {"-F/Qt"}, {"-I/"}, {"-I/etc/passwd"}, {"-I."}, @@ -62,6 +63,8 @@ var goodCompilerFlags = [][]string{ var badCompilerFlags = [][]string{ {"-D@X"}, {"-D-X"}, + {"-F@dir"}, + {"-F-dir"}, {"-I@dir"}, {"-I-dir"}, {"-O@1"}, @@ -125,6 +128,7 @@ var goodLinkerFlags = [][]string{ {"-Wl,--no-warn-error"}, {"foo.so"}, {"_世界.dll"}, + {"./x.o"}, {"libcgosotest.dylib"}, {"-F", "framework"}, {"-l", "."}, @@ -191,6 +195,7 @@ var badLinkerFlags = [][]string{ {"-x", "--c"}, {"-x", "@obj"}, {"-Wl,-rpath,@foo"}, + {"../x.o"}, } func TestCheckLinkerFlags(t *testing.T) { diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/go.mod b/libgo/go/cmd/go/testdata/modlegacy/src/new/go.mod new file mode 100644 index 0000000..d0dd46d --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/go.mod @@ -0,0 +1 @@ +module "new/v2" diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/new.go b/libgo/go/cmd/go/testdata/modlegacy/src/new/new.go new file mode 100644 index 0000000..e99c47a --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/new.go @@ -0,0 +1,3 @@ +package new + +import _ "new/v2/p2" diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/p1/p1.go b/libgo/go/cmd/go/testdata/modlegacy/src/new/p1/p1.go new file mode 100644 index 0000000..4539f40 --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/p1/p1.go @@ -0,0 +1,7 @@ +package p1 + +import _ "old/p2" +import _ "new/v2" +import _ "new/v2/p2" +import _ "new/sub/v2/x/v1/y" // v2 is module, v1 is directory in module +import _ "new/sub/inner/x" // new/sub/inner/go.mod overrides new/sub/go.mod diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/p2/p2.go b/libgo/go/cmd/go/testdata/modlegacy/src/new/p2/p2.go new file mode 100644 index 0000000..9b9052f --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/p2/p2.go @@ -0,0 +1 @@ +package p2 diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/go.mod b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/go.mod new file mode 100644 index 0000000..484d20c --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/go.mod @@ -0,0 +1 @@ +module new/sub/v2 diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod new file mode 100644 index 0000000..ba39345 --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod @@ -0,0 +1 @@ +module new/sub/inner diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go new file mode 100644 index 0000000..823aafd --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go @@ -0,0 +1 @@ +package x diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go new file mode 100644 index 0000000..789ca71 --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go @@ -0,0 +1 @@ +package y diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/old/p1/p1.go b/libgo/go/cmd/go/testdata/modlegacy/src/old/p1/p1.go new file mode 100644 index 0000000..9052748 --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/old/p1/p1.go @@ -0,0 +1,5 @@ +package p1 + +import _ "old/p2" +import _ "new/p1" +import _ "new" diff --git a/libgo/go/cmd/go/testdata/modlegacy/src/old/p2/p2.go b/libgo/go/cmd/go/testdata/modlegacy/src/old/p2/p2.go new file mode 100644 index 0000000..9b9052f --- /dev/null +++ b/libgo/go/cmd/go/testdata/modlegacy/src/old/p2/p2.go @@ -0,0 +1 @@ +package p2 diff --git a/libgo/go/cmd/go/vendor_test.go b/libgo/go/cmd/go/vendor_test.go index 4f21a51..0e7a633 100644 --- a/libgo/go/cmd/go/vendor_test.go +++ b/libgo/go/cmd/go/vendor_test.go @@ -10,6 +10,7 @@ import ( "bytes" "fmt" "internal/testenv" + "os" "path/filepath" "regexp" "strings" @@ -328,3 +329,75 @@ func TestVendor12156(t *testing.T) { tg.grepStderrNot("panic", "panicked") tg.grepStderr(`cannot find package "x"`, "wrong error") } + +// Module legacy support does path rewriting very similar to vendoring. + +func TestModLegacy(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/modlegacy")) + tg.run("list", "-f", "{{.Imports}}", "old/p1") + tg.grepStdout("new/p1", "old/p1 should import new/p1") + tg.run("list", "-f", "{{.Imports}}", "new/p1") + tg.grepStdout("new/p2", "new/p1 should import new/p2 (not new/v2/p2)") + tg.grepStdoutNot("new/v2", "new/p1 should NOT import new/v2*") + tg.grepStdout("new/sub/x/v1/y", "new/p1 should import new/sub/x/v1/y (not new/sub/v2/x/v1/y)") + tg.grepStdoutNot("new/sub/v2", "new/p1 should NOT import new/sub/v2*") + tg.grepStdout("new/sub/inner/x", "new/p1 should import new/sub/inner/x (no rewrites)") + tg.run("build", "old/p1", "new/p1") +} + +func TestModLegacyGet(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path("d1")) + tg.run("get", "vcs-test.golang.org/git/modlegacy1-old.git/p1") + tg.run("list", "-f", "{{.Deps}}", "vcs-test.golang.org/git/modlegacy1-old.git/p1") + tg.grepStdout("new.git/p2", "old/p1 should depend on new/p2") + tg.grepStdoutNot("new.git/v2/p2", "old/p1 should NOT depend on new/v2/p2") + tg.run("build", "vcs-test.golang.org/git/modlegacy1-old.git/p1", "vcs-test.golang.org/git/modlegacy1-new.git/p1") + + tg.setenv("GOPATH", tg.path("d2")) + + tg.must(os.RemoveAll(tg.path("d2"))) + tg.run("get", "github.com/rsc/vgotest5") + tg.run("get", "github.com/rsc/vgotest4") + tg.run("get", "github.com/myitcv/vgo_example_compat") + + if testing.Short() { + return + } + + tg.must(os.RemoveAll(tg.path("d2"))) + tg.run("get", "github.com/rsc/vgotest4") + tg.run("get", "github.com/rsc/vgotest5") + tg.run("get", "github.com/myitcv/vgo_example_compat") + + tg.must(os.RemoveAll(tg.path("d2"))) + tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5") + tg.run("get", "github.com/myitcv/vgo_example_compat") + + tg.must(os.RemoveAll(tg.path("d2"))) + tg.run("get", "github.com/rsc/vgotest5", "github.com/rsc/vgotest4") + tg.run("get", "github.com/myitcv/vgo_example_compat") + + tg.must(os.RemoveAll(tg.path("d2"))) + tg.run("get", "github.com/myitcv/vgo_example_compat") + tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5") + + pkgs := []string{"github.com/myitcv/vgo_example_compat", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5"} + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + for k := 0; k < 3; k++ { + if i == j || i == k || k == j { + continue + } + tg.must(os.RemoveAll(tg.path("d2"))) + tg.run("get", pkgs[i], pkgs[j], pkgs[k]) + } + } + } +} diff --git a/libgo/go/crypto/x509/name_constraints_test.go b/libgo/go/crypto/x509/name_constraints_test.go index bad488f..95d55fd 100644 --- a/libgo/go/crypto/x509/name_constraints_test.go +++ b/libgo/go/crypto/x509/name_constraints_test.go @@ -1222,8 +1222,9 @@ var nameConstraintsTests = []nameConstraintsTest{ }, }, - // #63: A specified key usage in an intermediate forbids other usages - // in the leaf. + // #63: An intermediate with enumerated EKUs causes a failure if we + // test for an EKU not in that set. (ServerAuth is required by + // default.) nameConstraintsTest{ roots: []constraintsSpec{ constraintsSpec{}, @@ -1239,11 +1240,11 @@ var nameConstraintsTests = []nameConstraintsTest{ sans: []string{"dns:example.com"}, ekus: []string{"serverAuth"}, }, - expectedError: "EKU not permitted", + expectedError: "incompatible key usage", }, - // #64: A specified key usage in an intermediate forbids other usages - // in the leaf, even if we don't recognise them. + // #64: an unknown EKU in the leaf doesn't break anything, even if it's not + // correctly nested. nameConstraintsTest{ roots: []constraintsSpec{ constraintsSpec{}, @@ -1259,7 +1260,7 @@ var nameConstraintsTests = []nameConstraintsTest{ sans: []string{"dns:example.com"}, ekus: []string{"other"}, }, - expectedError: "EKU not permitted", + requestedEKUs: []ExtKeyUsage{ExtKeyUsageAny}, }, // #65: trying to add extra permitted key usages in an intermediate @@ -1284,24 +1285,25 @@ var nameConstraintsTests = []nameConstraintsTest{ }, }, - // #66: EKUs in roots are ignored. + // #66: EKUs in roots are not ignored. nameConstraintsTest{ roots: []constraintsSpec{ constraintsSpec{ - ekus: []string{"serverAuth"}, + ekus: []string{"email"}, }, }, intermediates: [][]constraintsSpec{ []constraintsSpec{ constraintsSpec{ - ekus: []string{"serverAuth", "email"}, + ekus: []string{"serverAuth"}, }, }, }, leaf: leafSpec{ sans: []string{"dns:example.com"}, - ekus: []string{"serverAuth", "email"}, + ekus: []string{"serverAuth"}, }, + expectedError: "incompatible key usage", }, // #67: in order to support COMODO chains, SGC key usages permit @@ -1447,8 +1449,7 @@ var nameConstraintsTests = []nameConstraintsTest{ expectedError: "\"https://example.com/test\" is excluded", }, - // #75: While serverAuth in a CA certificate permits clientAuth in a leaf, - // serverAuth in a leaf shouldn't permit clientAuth when requested in + // #75: serverAuth in a leaf shouldn't permit clientAuth when requested in // VerifyOptions. nameConstraintsTest{ roots: []constraintsSpec{ @@ -1558,6 +1559,27 @@ var nameConstraintsTests = []nameConstraintsTest{ }, requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection}, }, + + // #81: EKUs that are not asserted in VerifyOpts are not required to be + // nested. + nameConstraintsTest{ + roots: []constraintsSpec{ + constraintsSpec{}, + }, + intermediates: [][]constraintsSpec{ + []constraintsSpec{ + constraintsSpec{ + ekus: []string{"serverAuth"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + // There's no email EKU in the intermediate. This would be rejected if + // full nesting was required. + ekus: []string{"email", "serverAuth"}, + }, + }, } func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go index 92cc716..3621a93 100644 --- a/libgo/go/crypto/x509/root_windows.go +++ b/libgo/go/crypto/x509/root_windows.go @@ -95,6 +95,12 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e return nil } +type _CertChainPolicyPara struct { + Size uint32 + Flags uint32 + ExtraPolicyPara unsafe.Pointer +} + // checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for // use as a certificate chain for a SSL/TLS server. func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error { @@ -108,13 +114,13 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex } sslPara.Size = uint32(unsafe.Sizeof(*sslPara)) - para := &syscall.CertChainPolicyPara{ - ExtraPolicyPara: uintptr(unsafe.Pointer(sslPara)), + para := &_CertChainPolicyPara{ + ExtraPolicyPara: unsafe.Pointer(sslPara), } para.Size = uint32(unsafe.Sizeof(*para)) status := syscall.CertChainPolicyStatus{} - err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status) + err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, (*syscall.CertChainPolicyPara)(unsafe.Pointer(para)), &status) if err != nil { return err } diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go index 0ea214b..60e415b 100644 --- a/libgo/go/crypto/x509/verify.go +++ b/libgo/go/crypto/x509/verify.go @@ -56,8 +56,7 @@ const ( // CPU time to verify. TooManyConstraints // CANotAuthorizedForExtKeyUsage results when an intermediate or root - // certificate does not permit an extended key usage that is claimed by - // the leaf certificate. + // certificate does not permit a requested extended key usage. CANotAuthorizedForExtKeyUsage ) @@ -82,7 +81,7 @@ func (e CertificateInvalidError) Error() string { case TooManyIntermediates: return "x509: too many intermediates for path length constraint" case IncompatibleUsage: - return "x509: certificate specifies an incompatible key usage: " + e.Detail + return "x509: certificate specifies an incompatible key usage" case NameMismatch: return "x509: issuer name does not match subject from issuing certificate" case NameConstraintsWithoutSANs: @@ -185,9 +184,8 @@ type VerifyOptions struct { // list means ExtKeyUsageServerAuth. To accept any key usage, include // ExtKeyUsageAny. // - // Certificate chains are required to nest extended key usage values, - // irrespective of this value. This matches the Windows CryptoAPI behavior, - // but not the spec. + // Certificate chains are required to nest these extended key usage values. + // (This matches the Windows CryptoAPI behavior, but not the spec.) KeyUsages []ExtKeyUsage // MaxConstraintComparisions is the maximum number of comparisons to // perform when checking a given certificate's name constraints. If @@ -549,51 +547,6 @@ func (c *Certificate) checkNameConstraints(count *int, return nil } -const ( - checkingAgainstIssuerCert = iota - checkingAgainstLeafCert -) - -// ekuPermittedBy returns true iff the given extended key usage is permitted by -// the given EKU from a certificate. Normally, this would be a simple -// comparison plus a special case for the “any” EKU. But, in order to support -// existing certificates, some exceptions are made. -func ekuPermittedBy(eku, certEKU ExtKeyUsage, context int) bool { - if certEKU == ExtKeyUsageAny || eku == certEKU { - return true - } - - // Some exceptions are made to support existing certificates. Firstly, - // the ServerAuth and SGC EKUs are treated as a group. - mapServerAuthEKUs := func(eku ExtKeyUsage) ExtKeyUsage { - if eku == ExtKeyUsageNetscapeServerGatedCrypto || eku == ExtKeyUsageMicrosoftServerGatedCrypto { - return ExtKeyUsageServerAuth - } - return eku - } - - eku = mapServerAuthEKUs(eku) - certEKU = mapServerAuthEKUs(certEKU) - - if eku == certEKU { - return true - } - - // If checking a requested EKU against the list in a leaf certificate there - // are fewer exceptions. - if context == checkingAgainstLeafCert { - return false - } - - // ServerAuth in a CA permits ClientAuth in the leaf. - return (eku == ExtKeyUsageClientAuth && certEKU == ExtKeyUsageServerAuth) || - // Any CA may issue an OCSP responder certificate. - eku == ExtKeyUsageOCSPSigning || - // Code-signing CAs can use Microsoft's commercial and - // kernel-mode EKUs. - (eku == ExtKeyUsageMicrosoftCommercialCodeSigning || eku == ExtKeyUsageMicrosoftKernelCodeSigning) && certEKU == ExtKeyUsageCodeSigning -} - // isValid performs validity checks on c given that it is a candidate to append // to the chain in currentChain. func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error { @@ -708,59 +661,6 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V } } - checkEKUs := certType == intermediateCertificate - - // If no extended key usages are specified, then all are acceptable. - if checkEKUs && (len(c.ExtKeyUsage) == 0 && len(c.UnknownExtKeyUsage) == 0) { - checkEKUs = false - } - - // If the “any” key usage is permitted, then no more checks are needed. - if checkEKUs { - for _, caEKU := range c.ExtKeyUsage { - comparisonCount++ - if caEKU == ExtKeyUsageAny { - checkEKUs = false - break - } - } - } - - if checkEKUs { - NextEKU: - for _, eku := range leaf.ExtKeyUsage { - if comparisonCount > maxConstraintComparisons { - return CertificateInvalidError{c, TooManyConstraints, ""} - } - - for _, caEKU := range c.ExtKeyUsage { - comparisonCount++ - if ekuPermittedBy(eku, caEKU, checkingAgainstIssuerCert) { - continue NextEKU - } - } - - oid, _ := oidFromExtKeyUsage(eku) - return CertificateInvalidError{c, CANotAuthorizedForExtKeyUsage, fmt.Sprintf("EKU not permitted: %#v", oid)} - } - - NextUnknownEKU: - for _, eku := range leaf.UnknownExtKeyUsage { - if comparisonCount > maxConstraintComparisons { - return CertificateInvalidError{c, TooManyConstraints, ""} - } - - for _, caEKU := range c.UnknownExtKeyUsage { - comparisonCount++ - if caEKU.Equal(eku) { - continue NextUnknownEKU - } - } - - return CertificateInvalidError{c, CANotAuthorizedForExtKeyUsage, fmt.Sprintf("EKU not permitted: %#v", eku)} - } - } - // KeyUsage status flags are ignored. From Engineering Security, Peter // Gutmann: A European government CA marked its signing certificates as // being valid for encryption only, but no-one noticed. Another @@ -861,63 +761,38 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e } } - requestedKeyUsages := make([]ExtKeyUsage, len(opts.KeyUsages)) - copy(requestedKeyUsages, opts.KeyUsages) - if len(requestedKeyUsages) == 0 { - requestedKeyUsages = append(requestedKeyUsages, ExtKeyUsageServerAuth) + var candidateChains [][]*Certificate + if opts.Roots.contains(c) { + candidateChains = append(candidateChains, []*Certificate{c}) + } else { + if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil { + return nil, err + } } - // If no key usages are specified, then any are acceptable. - checkEKU := len(c.ExtKeyUsage) > 0 - - for _, eku := range requestedKeyUsages { - if eku == ExtKeyUsageAny { - checkEKU = false - break - } + keyUsages := opts.KeyUsages + if len(keyUsages) == 0 { + keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} } - if checkEKU { - foundMatch := false - NextUsage: - for _, eku := range requestedKeyUsages { - for _, leafEKU := range c.ExtKeyUsage { - if ekuPermittedBy(eku, leafEKU, checkingAgainstLeafCert) { - foundMatch = true - break NextUsage - } - } + // If any key usage is acceptable then we're done. + for _, usage := range keyUsages { + if usage == ExtKeyUsageAny { + return candidateChains, nil } + } - if !foundMatch { - msg := "leaf contains the following, recognized EKUs: " - - for i, leafEKU := range c.ExtKeyUsage { - oid, ok := oidFromExtKeyUsage(leafEKU) - if !ok { - continue - } - - if i > 0 { - msg += ", " - } - msg += formatOID(oid) - } - - return nil, CertificateInvalidError{c, IncompatibleUsage, msg} + for _, candidate := range candidateChains { + if checkChainForKeyUsage(candidate, keyUsages) { + chains = append(chains, candidate) } } - var candidateChains [][]*Certificate - if opts.Roots.contains(c) { - candidateChains = append(candidateChains, []*Certificate{c}) - } else { - if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil { - return nil, err - } + if len(chains) == 0 { + return nil, CertificateInvalidError{c, IncompatibleUsage, ""} } - return candidateChains, nil + return chains, nil } func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { @@ -1078,3 +953,65 @@ func (c *Certificate) VerifyHostname(h string) error { return HostnameError{c, h} } + +func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { + usages := make([]ExtKeyUsage, len(keyUsages)) + copy(usages, keyUsages) + + if len(chain) == 0 { + return false + } + + usagesRemaining := len(usages) + + // We walk down the list and cross out any usages that aren't supported + // by each certificate. If we cross out all the usages, then the chain + // is unacceptable. + +NextCert: + for i := len(chain) - 1; i >= 0; i-- { + cert := chain[i] + if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 { + // The certificate doesn't have any extended key usage specified. + continue + } + + for _, usage := range cert.ExtKeyUsage { + if usage == ExtKeyUsageAny { + // The certificate is explicitly good for any usage. + continue NextCert + } + } + + const invalidUsage ExtKeyUsage = -1 + + NextRequestedUsage: + for i, requestedUsage := range usages { + if requestedUsage == invalidUsage { + continue + } + + for _, usage := range cert.ExtKeyUsage { + if requestedUsage == usage { + continue NextRequestedUsage + } else if requestedUsage == ExtKeyUsageServerAuth && + (usage == ExtKeyUsageNetscapeServerGatedCrypto || + usage == ExtKeyUsageMicrosoftServerGatedCrypto) { + // In order to support COMODO + // certificate chains, we have to + // accept Netscape or Microsoft SGC + // usages as equal to ServerAuth. + continue NextRequestedUsage + } + } + + usages[i] = invalidUsage + usagesRemaining-- + if usagesRemaining == 0 { + return false + } + } + } + + return true +} diff --git a/libgo/go/strings/strings.go b/libgo/go/strings/strings.go index 02c0320..05e8243 100644 --- a/libgo/go/strings/strings.go +++ b/libgo/go/strings/strings.go @@ -474,7 +474,7 @@ func Map(mapping func(rune) rune, s string) string { b = make([]byte, len(s)+utf8.UTFMax) nbytes = copy(b, s[:i]) if r >= 0 { - if r <= utf8.RuneSelf { + if r < utf8.RuneSelf { b[nbytes] = byte(r) nbytes++ } else { @@ -504,7 +504,7 @@ func Map(mapping func(rune) rune, s string) string { r := mapping(c) // common case - if (0 <= r && r <= utf8.RuneSelf) && nbytes < len(b) { + if (0 <= r && r < utf8.RuneSelf) && nbytes < len(b) { b[nbytes] = byte(r) nbytes++ continue diff --git a/libgo/go/strings/strings_test.go b/libgo/go/strings/strings_test.go index f2399f4..92122db 100644 --- a/libgo/go/strings/strings_test.go +++ b/libgo/go/strings/strings_test.go @@ -532,6 +532,7 @@ var upperTests = []StringTest{ {"longStrinGwitHmixofsmaLLandcAps", "LONGSTRINGWITHMIXOFSMALLANDCAPS"}, {"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", "LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS"}, {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char + {"a\u0080\U0010FFFF", "A\u0080\U0010FFFF"}, // test utf8.RuneSelf and utf8.MaxRune } var lowerTests = []StringTest{ @@ -542,6 +543,7 @@ var lowerTests = []StringTest{ {"longStrinGwitHmixofsmaLLandcAps", "longstringwithmixofsmallandcaps"}, {"LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS", "long\u0250string\u0250with\u0250nonascii\u0250chars"}, {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char + {"A\u0080\U0010FFFF", "a\u0080\U0010FFFF"}, // test utf8.RuneSelf and utf8.MaxRune } const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" @@ -654,6 +656,27 @@ func TestMap(t *testing.T) { if m != expect { t.Errorf("replace invalid sequence: expected %q got %q", expect, m) } + + // 8. Check utf8.RuneSelf and utf8.MaxRune encoding + encode := func(r rune) rune { + switch r { + case utf8.RuneSelf: + return unicode.MaxRune + case unicode.MaxRune: + return utf8.RuneSelf + } + return r + } + s := string(utf8.RuneSelf) + string(utf8.MaxRune) + r := string(utf8.MaxRune) + string(utf8.RuneSelf) // reverse of s + m = Map(encode, s) + if m != r { + t.Errorf("encoding not handled correctly: expected %q got %q", r, m) + } + m = Map(encode, r) + if m != s { + t.Errorf("encoding not handled correctly: expected %q got %q", s, m) + } } func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } diff --git a/libgo/misc/cgo/testcshared/main2.c b/libgo/misc/cgo/testcshared/main2.c index 6e8bf14..1a3f1d7 100644 --- a/libgo/misc/cgo/testcshared/main2.c +++ b/libgo/misc/cgo/testcshared/main2.c @@ -9,7 +9,7 @@ #include #include -#define fd (100) +#define fd (30) // Tests libgo2.so, which does not export any functions. // Read a string from the file descriptor and print it. diff --git a/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go b/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go index 1b69d8f..e57c93b 100644 --- a/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go +++ b/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go @@ -21,7 +21,7 @@ import ( // that the C code can also use. const ( - fd = 100 + fd = 30 ) func init() { -- cgit v1.1 From 27fbc519e01f3fd9d7c449074cac5af156cf5521 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 21 Jun 2018 23:02:25 +0000 Subject: cmd/go: re-enable a couple of tests of gccgo Port https://golang.org/cl/120375 over to the gofrontend repo so that it gets more reliable testing. Updates golang/go#22472 Reviewed-on: https://go-review.googlesource.com/120395 From-SVN: r261871 --- libgo/go/cmd/go/go_test.go | 2 -- 1 file changed, 2 deletions(-) (limited to 'libgo') diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go index f6d6f42..20606d8 100644 --- a/libgo/go/cmd/go/go_test.go +++ b/libgo/go/cmd/go/go_test.go @@ -791,7 +791,6 @@ func TestBuildComplex(t *testing.T) { tg.run("build", "-x", "-o", os.DevNull, "complex") if _, err := exec.LookPath("gccgo"); err == nil { - t.Skip("golang.org/issue/22472") tg.run("build", "-x", "-o", os.DevNull, "-compiler=gccgo", "complex") } } @@ -2944,7 +2943,6 @@ func TestIssue7573(t *testing.T) { if _, err := exec.LookPath("gccgo"); err != nil { t.Skip("skipping because no gccgo compiler found") } - t.Skip("golang.org/issue/22472") tg := testgo(t) defer tg.cleanup() -- cgit v1.1 From 38a4d6da179a0c88cc8b697470f928488e0553ee Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 22 Jun 2018 14:25:52 +0000 Subject: syscall: remove Ustat glibc 2.28 removes ustat.h and the ustat function entirely, which breaks syscall.Ustat. Updates golang/go#25990 Reviewed-on: https://go-review.googlesource.com/120535 From-SVN: r261896 --- libgo/config.h.in | 3 --- libgo/configure | 33 --------------------------------- libgo/configure.ac | 18 ------------------ libgo/go/syscall/libcall_linux_ustat.go | 12 ------------ libgo/mksysinfo.sh | 14 -------------- libgo/sysinfo.c | 3 --- 6 files changed, 83 deletions(-) delete mode 100644 libgo/go/syscall/libcall_linux_ustat.go (limited to 'libgo') diff --git a/libgo/config.h.in b/libgo/config.h.in index 57560cd..de57d0c 100644 --- a/libgo/config.h.in +++ b/libgo/config.h.in @@ -343,9 +343,6 @@ /* Define to 1 if you have the `unshare' function. */ #undef HAVE_UNSHARE -/* Define to 1 if you have the header file and it works. */ -#undef HAVE_USTAT_H - /* Define to 1 if you have the `utimensat' function. */ #undef HAVE_UTIMENSAT diff --git a/libgo/configure b/libgo/configure index 66942ed..7166f94 100755 --- a/libgo/configure +++ b/libgo/configure @@ -14760,39 +14760,6 @@ fi done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether can be used" >&5 -$as_echo_n "checking whether can be used... " >&6; } -if test "${libgo_cv_c_ustat_h+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - CFLAGS_hold=$CFLAGS -CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE $OSCFLAGS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#ifdef HAVE_LINUX_FILTER_H -#include -#endif -#include - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - libgo_cv_c_ustat_h=yes -else - libgo_cv_c_ustat_h=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -CFLAGS=$CFLAGS_hold -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_ustat_h" >&5 -$as_echo "$libgo_cv_c_ustat_h" >&6; } -if test $libgo_cv_c_ustat_h = yes; then - -$as_echo "#define HAVE_USTAT_H 1" >>confdefs.h - -fi - if test "$ac_cv_header_sys_mman_h" = yes; then HAVE_SYS_MMAN_H_TRUE= HAVE_SYS_MMAN_H_FALSE='#' diff --git a/libgo/configure.ac b/libgo/configure.ac index 3cee2c0..1c19275 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -537,24 +537,6 @@ AC_CHECK_HEADERS([linux/filter.h linux/if_addr.h linux/if_ether.h linux/if_tun.h #endif ]) -AC_CACHE_CHECK([whether can be used], -[libgo_cv_c_ustat_h], -[CFLAGS_hold=$CFLAGS -CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE $OSCFLAGS" -AC_COMPILE_IFELSE( -[AC_LANG_SOURCE([ -#include -#ifdef HAVE_LINUX_FILTER_H -#include -#endif -#include -])], [libgo_cv_c_ustat_h=yes], [libgo_cv_c_ustat_h=no]) -CFLAGS=$CFLAGS_hold]) -if test $libgo_cv_c_ustat_h = yes; then - AC_DEFINE(HAVE_USTAT_H, 1, - [Define to 1 if you have the header file and it works.]) -fi - AM_CONDITIONAL(HAVE_SYS_MMAN_H, test "$ac_cv_header_sys_mman_h" = yes) AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv unsetenv dl_iterate_phdr) diff --git a/libgo/go/syscall/libcall_linux_ustat.go b/libgo/go/syscall/libcall_linux_ustat.go deleted file mode 100644 index f515fce..0000000 --- a/libgo/go/syscall/libcall_linux_ustat.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2015 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. - -// GNU/Linux library ustat call. -// This is not supported on some kernels, such as arm64. -// +build !arm64,!nios2,!riscv64 - -package syscall - -//sys Ustat(dev int, ubuf *Ustat_t) (err error) -//ustat(dev _dev_t, ubuf *Ustat_t) _C_int diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh index 92ecb47..48bc71d 100755 --- a/libgo/mksysinfo.sh +++ b/libgo/mksysinfo.sh @@ -1164,20 +1164,6 @@ grep '^type _sysinfo ' gen-sysinfo.go | \ -e 's/mem_unit/Unit/' \ >> ${OUT} -# The ustat struct. -grep '^type _ustat ' gen-sysinfo.go | \ - sed -e 's/_ustat/Ustat_t/' \ - -e 's/f_tfree/Tfree/' \ - -e 's/f_tinode/Tinoe/' \ - -e 's/f_fname/Fname/' \ - -e 's/f_fpack/Fpack/' \ - >> ${OUT} -# Force it to be defined, as on some older GNU/Linux systems the -# header file fails when using with . -if ! grep 'type _ustat ' gen-sysinfo.go >/dev/null 2>&1; then - echo 'type Ustat_t struct { Tfree int32; Tinoe uint64; Fname [5+1]int8; Fpack [5+1]int8; }' >> ${OUT} -fi - # The utimbuf struct. grep '^type _utimbuf ' gen-sysinfo.go | \ sed -e 's/_utimbuf/Utimbuf/' \ diff --git a/libgo/sysinfo.c b/libgo/sysinfo.c index fb11826..4ab798c 100644 --- a/libgo/sysinfo.c +++ b/libgo/sysinfo.c @@ -144,9 +144,6 @@ #if defined(HAVE_SYS_SYSINFO_H) #include #endif -#if defined(HAVE_USTAT_H) -#include -#endif #if defined(HAVE_UTIME_H) #include #endif -- cgit v1.1 From 88d51f79961baba6c931ea9469469fbe2985e10d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 23 Jun 2018 02:44:36 +0000 Subject: runtime: use #ifdef instead of #if for USING_SPLIT_STACK USING_SPLIT_STACK is configured as defined/undefined, not 0/1. Most of the places test USING_SPLIT_STACK with #ifdef, with a few exceptions. This CL fixes the exceptions. Reviewed-on: https://go-review.googlesource.com/120596 From-SVN: r261980 --- libgo/runtime/proc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libgo') diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 12c055d..913ce5c 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -716,7 +716,7 @@ runtime_malg(bool allocatestack, bool signalstack, byte** ret_stack, uintptr* re G *newg; byte* unused_stack; uintptr unused_stacksize; -#if USING_SPLIT_STACK +#ifdef USING_SPLIT_STACK int dont_block_signals = 0; size_t ss_stacksize; #endif @@ -738,7 +738,7 @@ runtime_malg(bool allocatestack, bool signalstack, byte** ret_stack, uintptr* re #endif } -#if USING_SPLIT_STACK +#ifdef USING_SPLIT_STACK *ret_stack = __splitstack_makecontext(stacksize, (void*)(&newg->stackcontext[0]), &ss_stacksize); @@ -777,7 +777,7 @@ void stackfree(G*) void stackfree(G* gp) { -#if USING_SPLIT_STACK +#ifdef USING_SPLIT_STACK __splitstack_releasecontext((void*)(&gp->stackcontext[0])); #else // If gcstacksize is 0, the stack is allocated by libc and will be -- cgit v1.1 From 94e12bd4d9b7de6cc4a084c7b453a0e26210f56e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 28 Jun 2018 20:54:04 +0000 Subject: runtime: don't stat a NULL filename Noticed in https://gcc.gnu.org/PR86331. Reviewed-on: https://go-review.googlesource.com/121417 From-SVN: r262234 --- libgo/runtime/go-caller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libgo') diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c index 6b26ddc..7f36955 100644 --- a/libgo/runtime/go-caller.c +++ b/libgo/runtime/go-caller.c @@ -116,7 +116,7 @@ __go_get_backtrace_state () argv[0] (http://gcc.gnu.org/PR61895). It would be nice to have a better check for whether this file is the real executable. */ - if (stat (filename, &s) < 0 || s.st_size < 1024) + if (filename != NULL && (stat (filename, &s) < 0 || s.st_size < 1024)) filename = NULL; back_state = backtrace_create_state (filename, 1, error_callback, NULL); -- cgit v1.1 From 7edd4c1885f4ecc31b80f157f7aa96ccd40d1075 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 2 Jul 2018 16:28:43 +0000 Subject: re PR go/86331 (the gccgo's "go" tool looks like failing to invoke any sub go command) PR go/86331 os: check return value as well as error from waitid https://gcc.gnu.org/PR86331 indicates that if a signal handler runs it is possible for syscall.Syscall6 to return a non-zero errno value even if no error occurs. That is a problem in general, but this fix will let us work around the general problem for the specific case of calling waitid. Reviewed-on: https://go-review.googlesource.com/121595 From-SVN: r262313 --- libgo/go/os/wait_waitid.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'libgo') diff --git a/libgo/go/os/wait_waitid.go b/libgo/go/os/wait_waitid.go index 5a62b27..a6284aa 100644 --- a/libgo/go/os/wait_waitid.go +++ b/libgo/go/os/wait_waitid.go @@ -28,9 +28,12 @@ func (p *Process) blockUntilWaitable() (bool, error) { // We don't care about the values it returns. var siginfo [16]uint64 psig := &siginfo[0] - _, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0) + r, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0) runtime.KeepAlive(p) - if e != 0 { + // Check r as well as e because syscall.Syscall6 currently + // just returns errno, and the SIGCHLD signal handler may + // change errno. See https://gcc.gnu.org/PR86331. + if r != 0 && e != 0 { // waitid has been available since Linux 2.6.9, but // reportedly is not available in Ubuntu on Windows. // See issue 16610. -- cgit v1.1 From 867b003fd74a1f77c9835a8c64e1dcf88f639aff Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 13 Jul 2018 20:39:02 +0000 Subject: runtime: skip zero-sized fields in structs when converting to FFI The libffi library doesn't understand zero-sized objects. When we see a zero-sized field in a struct, just skip it when converting to the FFI data structures. There is no value to pass in any case, so not telling libffi about the field doesn't affect anything. The test case for this is https://golang.org/cl/123316. Fixes golang/go#26335 Reviewed-on: https://go-review.googlesource.com/123335 From-SVN: r262651 --- libgo/go/runtime/ffi.go | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) (limited to 'libgo') diff --git a/libgo/go/runtime/ffi.go b/libgo/go/runtime/ffi.go index 164e177..00858f1 100644 --- a/libgo/go/runtime/ffi.go +++ b/libgo/go/runtime/ffi.go @@ -225,11 +225,40 @@ func structToFFI(typ *structtype) *__ffi_type { return emptyStructToFFI() } - fields := make([]*__ffi_type, c+1) + fields := make([]*__ffi_type, 0, c+1) + checkPad := false for i, v := range typ.fields { - fields[i] = typeToFFI(v.typ) + // Skip zero-sized fields; they confuse libffi, + // and there is no value to pass in any case. + // We do have to check whether the alignment of the + // zero-sized field introduces any padding for the + // next field. + if v.typ.size == 0 { + checkPad = true + continue + } + + if checkPad { + off := uintptr(0) + for j := i - 1; j >= 0; j-- { + if typ.fields[j].typ.size > 0 { + off = typ.fields[j].offset() + typ.fields[j].typ.size + break + } + } + off += uintptr(v.typ.align) - 1 + off &^= uintptr(v.typ.align) - 1 + if off != v.offset() { + fields = append(fields, padFFI(v.offset()-off)) + } + checkPad = false + } + + fields = append(fields, typeToFFI(v.typ)) } - fields[c] = nil + + fields = append(fields, nil) + return &__ffi_type{ _type: _FFI_TYPE_STRUCT, elements: &fields[0], @@ -305,6 +334,19 @@ func emptyStructToFFI() *__ffi_type { } } +// padFFI returns a padding field of the given size +func padFFI(size uintptr) *__ffi_type { + elements := make([]*__ffi_type, size+1) + for i := uintptr(0); i < size; i++ { + elements[i] = ffi_type_uint8() + } + elements[size] = nil + return &__ffi_type{ + _type: _FFI_TYPE_STRUCT, + elements: &elements[0], + } +} + //go:linkname makeCIF reflect.makeCIF // makeCIF is used by the reflect package to allocate a CIF. -- cgit v1.1 From 5ac2fd0d6edd8198ed10b66f48402678471c044c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 27 Jul 2018 18:43:34 +0000 Subject: libgo: prune sighandler frames in runtime.sigprof When writing stack frames to the pprof CPU profile machinery, it is very important to insure that the frames emitted do not contain any frames corresponding to artifacts of the profiling process itself (signal handlers, sigprof, etc). This patch changes runtime.sigprof to strip out those frames from the raw stack generated by "runtime.callers". Fixes golang/go#26595. Reviewed-on: https://go-review.googlesource.com/126175 From-SVN: r263035 --- libgo/go/runtime/pprof/pprof_test.go | 51 +++++++++++++++++++++++++++++------- libgo/go/runtime/proc.go | 30 ++++++++++++++++++++- 2 files changed, 70 insertions(+), 11 deletions(-) (limited to 'libgo') diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go index 07a7946..02d99f5 100644 --- a/libgo/go/runtime/pprof/pprof_test.go +++ b/libgo/go/runtime/pprof/pprof_test.go @@ -72,15 +72,24 @@ func cpuHog2(x int) int { return foo } +// Return a list of functions that we don't want to ever appear in CPU +// profiles. For gccgo, that list includes the sigprof handler itself. +func avoidFunctions() []string { + if runtime.Compiler == "gccgo" { + return []string{"runtime.sigprof"} + } + return nil +} + func TestCPUProfile(t *testing.T) { - testCPUProfile(t, []string{"pprof.cpuHog1"}, func(dur time.Duration) { + testCPUProfile(t, []string{"pprof.cpuHog1"}, avoidFunctions(), func(dur time.Duration) { cpuHogger(cpuHog1, &salt1, dur) }) } func TestCPUProfileMultithreaded(t *testing.T) { defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2)) - testCPUProfile(t, []string{"pprof.cpuHog1", "pprof.cpuHog2"}, func(dur time.Duration) { + testCPUProfile(t, []string{"pprof.cpuHog1", "pprof.cpuHog2"}, avoidFunctions(), func(dur time.Duration) { c := make(chan int) go func() { cpuHogger(cpuHog1, &salt1, dur) @@ -92,7 +101,7 @@ func TestCPUProfileMultithreaded(t *testing.T) { } func TestCPUProfileInlining(t *testing.T) { - testCPUProfile(t, []string{"pprof.inlinedCallee", "pprof.inlinedCaller"}, func(dur time.Duration) { + testCPUProfile(t, []string{"pprof.inlinedCallee", "pprof.inlinedCaller"}, avoidFunctions(), func(dur time.Duration) { cpuHogger(inlinedCaller, &salt1, dur) }) } @@ -130,7 +139,7 @@ func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []*profile.Loca } } -func testCPUProfile(t *testing.T, need []string, f func(dur time.Duration)) { +func testCPUProfile(t *testing.T, need []string, avoid []string, f func(dur time.Duration)) { switch runtime.GOOS { case "darwin": switch runtime.GOARCH { @@ -169,7 +178,7 @@ func testCPUProfile(t *testing.T, need []string, f func(dur time.Duration)) { f(duration) StopCPUProfile() - if profileOk(t, need, prof, duration) { + if profileOk(t, need, avoid, prof, duration) { return } @@ -202,11 +211,13 @@ func contains(slice []string, s string) bool { return false } -func profileOk(t *testing.T, need []string, prof bytes.Buffer, duration time.Duration) (ok bool) { +func profileOk(t *testing.T, need []string, avoid []string, prof bytes.Buffer, duration time.Duration) (ok bool) { ok = true - // Check that profile is well formed and contains need. + // Check that profile is well formed, contains 'need', and does not contain + // anything from 'avoid'. have := make([]uintptr, len(need)) + avoidSamples := make([]uintptr, len(avoid)) var samples uintptr var buf bytes.Buffer parseProfile(t, prof.Bytes(), func(count uintptr, stk []*profile.Location, labels map[string][]string) { @@ -229,6 +240,15 @@ func profileOk(t *testing.T, need []string, prof bytes.Buffer, duration time.Dur } } } + for i, name := range avoid { + for _, loc := range stk { + for _, line := range loc.Line { + if strings.Contains(line.Function.Name, name) { + avoidSamples[i] += count + } + } + } + } fmt.Fprintf(&buf, "\n") }) t.Logf("total %d CPU profile samples collected:\n%s", samples, buf.String()) @@ -251,6 +271,14 @@ func profileOk(t *testing.T, need []string, prof bytes.Buffer, duration time.Dur ok = false } + for i, name := range avoid { + bad := avoidSamples[i] + if bad != 0 { + t.Logf("found %d samples in avoid-function %s\n", bad, name) + ok = false + } + } + if len(need) == 0 { return ok } @@ -318,6 +346,9 @@ func TestCPUProfileWithFork(t *testing.T) { // If it did, it would see inconsistent state and would either record an incorrect stack // or crash because the stack was malformed. func TestGoroutineSwitch(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("not applicable for gccgo") + } // How much to try. These defaults take about 1 seconds // on a 2012 MacBook Pro. The ones in short mode take // about 0.1 seconds. @@ -377,7 +408,7 @@ func fprintStack(w io.Writer, stk []*profile.Location) { // Test that profiling of division operations is okay, especially on ARM. See issue 6681. func TestMathBigDivide(t *testing.T) { - testCPUProfile(t, nil, func(duration time.Duration) { + testCPUProfile(t, nil, nil, func(duration time.Duration) { t := time.After(duration) pi := new(big.Int) for { @@ -851,7 +882,7 @@ func TestEmptyCallStack(t *testing.T) { } func TestCPUProfileLabel(t *testing.T) { - testCPUProfile(t, []string{"pprof.cpuHogger;key=value"}, func(dur time.Duration) { + testCPUProfile(t, []string{"pprof.cpuHogger;key=value"}, avoidFunctions(), func(dur time.Duration) { Do(context.Background(), Labels("key", "value"), func(context.Context) { cpuHogger(cpuHog1, &salt1, dur) }) @@ -862,7 +893,7 @@ func TestLabelRace(t *testing.T) { // Test the race detector annotations for synchronization // between settings labels and consuming them from the // profile. - testCPUProfile(t, []string{"pprof.cpuHogger;key=value"}, func(dur time.Duration) { + testCPUProfile(t, []string{"pprof.cpuHogger;key=value"}, avoidFunctions(), func(dur time.Duration) { start := time.Now() var wg sync.WaitGroup for time.Since(start) < dur { diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index a6746c9..5826958 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -3418,8 +3418,36 @@ func sigprof(pc uintptr, gp *g, mp *m) { var stklocs [maxCPUProfStack]location n = callers(0, stklocs[:]) + // Issue 26595: the stack trace we've just collected is going + // to include frames that we don't want to report in the CPU + // profile, including signal handler frames. Here is what we + // might typically see at the point of "callers" above for a + // signal delivered to the application routine "interesting" + // called by "main". + // + // 0: runtime.sigprof + // 1: runtime.sighandler + // 2: runtime.sigtrampgo + // 3: runtime.sigtramp + // 4: + // 5: main.interesting_routine + // 6: main.main + // + // To ensure a sane profile, walk through the frames in + // "stklocs" until we find the "runtime.sigtramp" frame, then + // report only those frames below the frame one down from + // that. If for some reason "runtime.sigtramp" is not present, + // don't make any changes. + framesToDiscard := 0 + for i := 0; i < n; i++ { + if stklocs[i].function == "runtime.sigtramp" && i+2 < n { + framesToDiscard = i + 2 + n -= framesToDiscard + break + } + } for i := 0; i < n; i++ { - stk[i] = stklocs[i].pc + stk[i] = stklocs[i+framesToDiscard].pc } } -- cgit v1.1