libgo: update to Go1.10rc2
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 8 Feb 2018 15:30:22 +0000 (15:30 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 8 Feb 2018 15:30:22 +0000 (15:30 +0000)
    Reviewed-on: https://go-review.googlesource.com/92736

From-SVN: r257493

39 files changed:
gcc/go/gofrontend/MERGE
libgo/MERGE
libgo/VERSION
libgo/go/cmd/cgo/doc.go
libgo/go/cmd/cgo/gcc.go
libgo/go/cmd/go/alldocs.go
libgo/go/cmd/go/go_test.go
libgo/go/cmd/go/internal/cache/default.go
libgo/go/cmd/go/internal/envcmd/env.go
libgo/go/cmd/go/internal/help/helpdoc.go
libgo/go/cmd/go/internal/load/pkg.go
libgo/go/cmd/go/internal/test/test.go
libgo/go/cmd/go/internal/work/exec.go
libgo/go/cmd/go/internal/work/security.go [new file with mode: 0644]
libgo/go/cmd/go/internal/work/security_test.go [new file with mode: 0644]
libgo/go/database/sql/driver/driver.go
libgo/go/database/sql/fakedb_test.go
libgo/go/database/sql/sql_test.go
libgo/go/go/build/deps_test.go
libgo/go/go/internal/gccgoimporter/gccgoinstallation_test.go
libgo/go/net/sock_bsd.go
libgo/go/os/exec.go
libgo/go/os/exec/exec.go
libgo/go/os/signal/internal/pty/pty.go
libgo/go/os/signal/signal_cgo_test.go
libgo/go/runtime/crash_cgo_test.go
libgo/go/runtime/testdata/testprogcgo/sigpanic.go [new file with mode: 0644]
libgo/go/text/template/doc.go
libgo/go/text/template/exec.go
libgo/go/text/template/exec_test.go
libgo/go/text/template/parse/lex.go
libgo/go/text/template/parse/lex_test.go
libgo/go/text/template/parse/node.go
libgo/go/text/template/parse/parse.go
libgo/go/text/template/parse/parse_test.go
libgo/misc/cgo/errors/src/err1.go
libgo/misc/cgo/test/issue19832.go [deleted file]
libgo/misc/cgo/test/issue4029.c
libgo/misc/cgo/test/issue4029.go

index f1a437706908d7f0c360c1930ce8d398f3ae037a..bdaea8180f4107c1a9946dabc11da62bc8a0a149 100644 (file)
@@ -1,4 +1,4 @@
-cdc28627b7abfd73f5d552813db8eb4293b823b0
+2aa95f1499cf931ef8e95c7958463829276a0f2c
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 4a3c64ed88f381c302e3172a79895ede2f31d789..26b8869db901594eb577bde77d3e3cb12a0977f3 100644 (file)
@@ -1,4 +1,4 @@
-5348aed83e39bd1d450d92d7f627e994c2db6ebf
+20e228f2fdb44350c858de941dff4aea9f3127b8
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
index 5859fbe0b7adb26d9cd28ba25f2b1c6045e0276e..dc3cdca6363558938f9b3dea6f00d2eaa65fffbe 100644 (file)
@@ -1 +1 @@
-go1.10rc1
+go1.10rc2
index 8e4cd88b37c2f7abe219fd8383bab44183ecba95..c16b63a313bb96c6dae51b435b8216ce97a85e20 100644 (file)
@@ -45,8 +45,8 @@ For example:
        // #include <png.h>
        import "C"
 
-Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config
-tool using a '#cgo pkg-config:' directive followed by the package names.
+Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config tool
+using a '#cgo pkg-config:' directive followed by the package names.
 For example:
 
        // #cgo pkg-config: png cairo
@@ -55,11 +55,21 @@ For example:
 
 The default pkg-config tool may be changed by setting the PKG_CONFIG environment variable.
 
+For security reasons, only a limited set of flags are allowed, notably -D, -I, and -l.
+To allow additional flags, set CGO_CFLAGS_ALLOW to a regular expression
+matching the new flags. To disallow flags that would otherwise be allowed,
+set CGO_CFLAGS_DISALLOW to a regular expression matching arguments
+that must be disallowed. In both cases the regular expression must match
+a full argument: to allow -mfoo=bar, use CGO_CFLAGS_ALLOW='-mfoo.*',
+not just CGO_CFLAGS_ALLOW='-mfoo'. Similarly named variables control
+the allowed CPPFLAGS, CXXFLAGS, FFLAGS, and LDFLAGS.
+
 When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and
 CGO_LDFLAGS environment variables are added to the flags derived from
 these directives. Package-specific flags should be set using the
 directives, not the environment variables, so that builds work in
-unmodified environments.
+unmodified environments. Flags obtained from environment variables
+are not subject to the security limitations described above.
 
 All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and
 used to compile C files in that package. All the CPPFLAGS and CXXFLAGS
index fcf334ec44efeb1694b8eadd3114538a72ccb5ca..534fba17eb4bbfe5155d0f7ae212c13dff2f7a7c 100644 (file)
@@ -2345,12 +2345,6 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
                                break
                        }
 
-                       // If we already know the typedef for t just use that.
-                       // See issue 19832.
-                       if def := typedef[t.Go.(*ast.Ident).Name]; def != nil {
-                               break
-                       }
-
                        t = c.Type(ptr, pos)
                        if t == nil {
                                return nil
index 85b9d2584f242a643cc2890a5fccc3091376ad8f..5e1ac5aaf571f90fa5f6a58aee4a43b131e151c2 100644 (file)
 //     CGO_CFLAGS
 //             Flags that cgo will pass to the compiler when compiling
 //             C code.
-//     CGO_CPPFLAGS
-//             Flags that cgo will pass to the compiler when compiling
-//             C or C++ code.
-//     CGO_CXXFLAGS
-//             Flags that cgo will pass to the compiler when compiling
-//             C++ code.
-//     CGO_FFLAGS
-//             Flags that cgo will pass to the compiler when compiling
-//             Fortran code.
-//     CGO_LDFLAGS
-//             Flags that cgo will pass to the compiler when linking.
+//     CGO_CFLAGS_ALLOW
+//             A regular expression specifying additional flags to allow
+//             to appear in #cgo CFLAGS source code directives.
+//             Does not apply to the CGO_CFLAGS environment variable.
+//     CGO_CFLAGS_DISALLOW
+//             A regular expression specifying flags that must be disallowed
+//             from appearing in #cgo CFLAGS source code directives.
+//             Does not apply to the CGO_CFLAGS environment variable.
+//     CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW
+//             Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+//             but for the C preprocessor.
+//     CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW
+//             Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+//             but for the C++ compiler.
+//     CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW
+//             Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+//             but for the Fortran compiler.
+//     CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW
+//             Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+//             but for the linker.
 //     CXX
 //             The command to use to compile C++ code.
 //     PKG_CONFIG
index 41a37a575b64173eaf8323faee6c690e66028a36..c5a3d7b36bc5cf4e943a35842296532e6b1a7462 100644 (file)
@@ -81,6 +81,13 @@ func init() {
                        skipExternal = true
                        canRun = false
                }
+       case "plan9":
+               switch runtime.GOARCH {
+               case "arm":
+                       // many plan9/arm machines are too slow to run
+                       // the full set of external tests.
+                       skipExternal = true
+               }
        case "windows":
                exeSuffix = ".exe"
        }
@@ -2815,7 +2822,7 @@ func TestCgoHandlesWlORIGIN(t *testing.T) {
        defer tg.cleanup()
        tg.parallel()
        tg.tempFile("src/origin/origin.go", `package origin
-               // #cgo !darwin LDFLAGS: -Wl,-rpath -Wl,$ORIGIN
+               // #cgo !darwin LDFLAGS: -Wl,-rpath,$ORIGIN
                // void f(void) {}
                import "C"
                func f() { C.f() }`)
@@ -5421,6 +5428,30 @@ func TestTestCacheInputs(t *testing.T) {
        }
 }
 
+func TestNoCache(t *testing.T) {
+       switch runtime.GOOS {
+       case "windows":
+               t.Skipf("no unwritable directories on %s", runtime.GOOS)
+       }
+       if os.Getuid() == 0 {
+               t.Skip("skipping test because running as root")
+       }
+
+       tg := testgo(t)
+       defer tg.cleanup()
+       tg.parallel()
+       tg.tempFile("triv.go", `package main; func main() {}`)
+       tg.must(os.MkdirAll(tg.path("unwritable"), 0555))
+       home := "HOME"
+       if runtime.GOOS == "plan9" {
+               home = "home"
+       }
+       tg.setenv(home, tg.path(filepath.Join("unwritable", "home")))
+       tg.unsetenv("GOCACHE")
+       tg.run("build", "-o", tg.path("triv"), tg.path("triv.go"))
+       tg.grepStderr("disabling cache", "did not disable cache")
+}
+
 func TestTestVet(t *testing.T) {
        tooSlow(t)
        tg := testgo(t)
@@ -5463,6 +5494,44 @@ func TestTestVet(t *testing.T) {
        tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2")
 }
 
+func TestTestRebuild(t *testing.T) {
+       tg := testgo(t)
+       defer tg.cleanup()
+       tg.parallel()
+
+       // golang.org/issue/23701.
+       // b_test imports b with augmented method from export_test.go.
+       // b_test also imports a, which imports b.
+       // Must not accidentally see un-augmented b propagate through a to b_test.
+       tg.tempFile("src/a/a.go", `package a
+               import "b"
+               type Type struct{}
+               func (*Type) M() b.T {return 0}
+       `)
+       tg.tempFile("src/b/b.go", `package b
+               type T int
+               type I interface {M() T}
+       `)
+       tg.tempFile("src/b/export_test.go", `package b
+               func (*T) Method() *T { return nil }
+       `)
+       tg.tempFile("src/b/b_test.go", `package b_test
+               import (
+                       "testing"
+                       "a"
+                       . "b"
+               )
+               func TestBroken(t *testing.T) {
+                       x := new(T)
+                       x.Method()
+                       _ = new(a.Type)
+               }
+       `)
+
+       tg.setenv("GOPATH", tg.path("."))
+       tg.run("test", "b")
+}
+
 func TestInstallDeps(t *testing.T) {
        tooSlow(t)
        tg := testgo(t)
@@ -5712,3 +5781,177 @@ func TestCpuprofileTwice(t *testing.T) {
        tg.run("test", "-o="+bin, "-cpuprofile="+out, "x")
        tg.mustExist(out)
 }
+
+// Issue 23694.
+func TestAtomicCoverpkgAll(t *testing.T) {
+       skipIfGccgo(t, "gccgo has no cover tool")
+       tg := testgo(t)
+       defer tg.cleanup()
+       tg.parallel()
+
+       tg.tempFile("src/x/x.go", `package x; import _ "sync/atomic"; func F() {}`)
+       tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`)
+       tg.setenv("GOPATH", tg.path("."))
+       tg.run("test", "-coverpkg=all", "-covermode=atomic", "x")
+       if canRace {
+               tg.run("test", "-coverpkg=all", "-race", "x")
+       }
+}
+
+func TestBadCommandLines(t *testing.T) {
+       tg := testgo(t)
+       defer tg.cleanup()
+
+       tg.tempFile("src/x/x.go", "package x\n")
+       tg.setenv("GOPATH", tg.path("."))
+
+       tg.run("build", "x")
+
+       tg.tempFile("src/x/@y.go", "package x\n")
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
+       tg.must(os.Remove(tg.path("src/x/@y.go")))
+
+       tg.tempFile("src/x/-y.go", "package x\n")
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
+       tg.must(os.Remove(tg.path("src/x/-y.go")))
+
+       if runtime.Compiler == "gccgo" {
+               tg.runFail("build", "-gccgoflags=all=@x", "x")
+       } else {
+               tg.runFail("build", "-gcflags=all=@x", "x")
+       }
+       tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
+
+       tg.tempFile("src/@x/x.go", "package x\n")
+       tg.setenv("GOPATH", tg.path("."))
+       tg.runFail("build", "@x")
+       tg.grepStderr("invalid input directory name \"@x\"", "did not reject @x directory")
+
+       tg.tempFile("src/@x/y/y.go", "package y\n")
+       tg.setenv("GOPATH", tg.path("."))
+       tg.runFail("build", "@x/y")
+       tg.grepStderr("invalid import path \"@x/y\"", "did not reject @x/y import path")
+
+       tg.tempFile("src/-x/x.go", "package x\n")
+       tg.setenv("GOPATH", tg.path("."))
+       tg.runFail("build", "--", "-x")
+       tg.grepStderr("invalid input directory name \"-x\"", "did not reject -x directory")
+
+       tg.tempFile("src/-x/y/y.go", "package y\n")
+       tg.setenv("GOPATH", tg.path("."))
+       tg.runFail("build", "--", "-x/y")
+       tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
+}
+
+func TestBadCgoDirectives(t *testing.T) {
+       if !canCgo {
+               t.Skip("no cgo")
+       }
+       tg := testgo(t)
+       defer tg.cleanup()
+
+       tg.tempFile("src/x/x.go", "package x\n")
+       tg.setenv("GOPATH", tg.path("."))
+
+       if runtime.Compiler == "gc" {
+               tg.tempFile("src/x/x.go", `package x
+
+                       //go:cgo_ldflag "-fplugin=foo.so"
+
+                       import "C"
+               `)
+               tg.runFail("build", "x")
+               tg.grepStderr("//go:cgo_ldflag .* only allowed in cgo-generated code", "did not reject //go:cgo_ldflag directive")
+       }
+
+       tg.must(os.Remove(tg.path("src/x/x.go")))
+       tg.runFail("build", "x")
+       tg.grepStderr("no Go files", "did not report missing source code")
+       tg.tempFile("src/x/_cgo_yy.go", `package x
+
+               //go:cgo_ldflag "-fplugin=foo.so"
+
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("no Go files", "did not report missing source code") // _* files are ignored...
+
+       if runtime.Compiler == "gc" {
+               tg.runFail("build", tg.path("src/x/_cgo_yy.go")) // ... but if forced, the comment is rejected
+               // Actually, today there is a separate issue that _ files named
+               // on the command-line are ignored. Once that is fixed,
+               // we want to see the cgo_ldflag error.
+               tg.grepStderr("//go:cgo_ldflag only allowed in cgo-generated code|no Go files", "did not reject //go:cgo_ldflag directive")
+       }
+
+       tg.must(os.Remove(tg.path("src/x/_cgo_yy.go")))
+
+       tg.tempFile("src/x/x.go", "package x\n")
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo CFLAGS: -fplugin=foo.so
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin")
+
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo CFLAGS: -Ibar -fplugin=foo.so
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin")
+
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo pkg-config: -foo
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid pkg-config package name: -foo", "did not reject pkg-config: -foo")
+
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo pkg-config: @foo
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid pkg-config package name: @foo", "did not reject pkg-config: -foo")
+
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo CFLAGS: @foo
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid flag in #cgo CFLAGS: @foo", "did not reject @foo flag")
+
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo CFLAGS: -D
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid flag in #cgo CFLAGS: -D without argument", "did not reject trailing -I flag")
+
+       // Note that -I @foo is allowed because we rewrite it into -I /path/to/src/@foo
+       // before the check is applied. There's no such rewrite for -D.
+
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo CFLAGS: -D @foo
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid flag in #cgo CFLAGS: -D @foo", "did not reject -D @foo flag")
+
+       tg.tempFile("src/x/y.go", `package x
+               // #cgo CFLAGS: -D@foo
+               import "C"
+       `)
+       tg.runFail("build", "x")
+       tg.grepStderr("invalid flag in #cgo CFLAGS: -D@foo", "did not reject -D@foo flag")
+
+       tg.setenv("CGO_CFLAGS", "-D@foo")
+       tg.tempFile("src/x/y.go", `package x
+               import "C"
+       `)
+       tg.run("build", "-n", "x")
+       tg.grepStderr("-D@foo", "did not find -D@foo in commands")
+}
index 8285f787d4c9cae46b178f6ecee94ae538fdcfbe..97283762258d659c0a6fcacc5d9c32fe80eebc88 100644 (file)
@@ -5,7 +5,7 @@
 package cache
 
 import (
-       "cmd/go/internal/base"
+       "fmt"
        "io/ioutil"
        "os"
        "path/filepath"
@@ -40,7 +40,8 @@ func initDefaultCache() {
                return
        }
        if err := os.MkdirAll(dir, 0777); err != nil {
-               base.Fatalf("initializing cache in $GOCACHE: %s", err)
+               fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
+               return
        }
        if _, err := os.Stat(filepath.Join(dir, "README")); err != nil {
                // Best effort.
@@ -49,7 +50,8 @@ func initDefaultCache() {
 
        c, err := Open(dir)
        if err != nil {
-               base.Fatalf("initializing cache in $GOCACHE: %s", err)
+               fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
+               return
        }
        defaultCache = c
 }
index fa19bebe218fcf8fc130cba5f123d8dcd330dd51..603f7b5060c98522a930c380effa9e7eaa8b0581 100644 (file)
@@ -113,7 +113,12 @@ func findEnv(env []cfg.EnvVar, name string) string {
 func ExtraEnvVars() []cfg.EnvVar {
        var b work.Builder
        b.Init()
-       cppflags, cflags, cxxflags, fflags, ldflags := b.CFlags(&load.Package{})
+       cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{})
+       if err != nil {
+               // Should not happen - b.CFlags was given an empty package.
+               fmt.Fprintf(os.Stderr, "go: invalid cflags: %v\n", err)
+               return nil
+       }
        cmd := b.GccCmd(".", "")
        return []cfg.EnvVar{
                // Note: Update the switch in runEnv below when adding to this list.
index 126e8663fb43d20a12ce560f573e809c4bf78f19..9a9fc4e944891c2eefb8704a242c3c2546684683 100644 (file)
@@ -487,17 +487,26 @@ Environment variables for use with cgo:
        CGO_CFLAGS
                Flags that cgo will pass to the compiler when compiling
                C code.
-       CGO_CPPFLAGS
-               Flags that cgo will pass to the compiler when compiling
-               C or C++ code.
-       CGO_CXXFLAGS
-               Flags that cgo will pass to the compiler when compiling
-               C++ code.
-       CGO_FFLAGS
-               Flags that cgo will pass to the compiler when compiling
-               Fortran code.
-       CGO_LDFLAGS
-               Flags that cgo will pass to the compiler when linking.
+       CGO_CFLAGS_ALLOW
+               A regular expression specifying additional flags to allow
+               to appear in #cgo CFLAGS source code directives.
+               Does not apply to the CGO_CFLAGS environment variable.
+       CGO_CFLAGS_DISALLOW
+               A regular expression specifying flags that must be disallowed
+               from appearing in #cgo CFLAGS source code directives.
+               Does not apply to the CGO_CFLAGS environment variable.
+       CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW
+               Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+               but for the C preprocessor.
+       CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW
+               Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+               but for the C++ compiler.
+       CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW
+               Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+               but for the Fortran compiler.
+       CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW
+               Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
+               but for the linker.
        CXX
                The command to use to compile C++ code.
        PKG_CONFIG
index 609a47db4bc4b072a1abfa669320a0d4145508fd..ac764b4d028605f0b74737bae851a0fbf63e3794 100644 (file)
@@ -17,6 +17,7 @@ import (
        "sort"
        "strings"
        "unicode"
+       "unicode/utf8"
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
@@ -55,6 +56,8 @@ type PackagePublic struct {
        StaleReason string `json:",omitempty"` // why is Stale true?
 
        // Source files
+       // If you add to this list you MUST add to p.AllFiles (below) too.
+       // Otherwise file name security lists will not apply to any new additions.
        GoFiles        []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
        CgoFiles       []string `json:",omitempty"` // .go sources files that import "C"
        IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints
@@ -86,12 +89,38 @@ type PackagePublic struct {
        DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
 
        // Test information
+       // If you add to this list you MUST add to p.AllFiles (below) too.
+       // Otherwise file name security lists will not apply to any new additions.
        TestGoFiles  []string `json:",omitempty"` // _test.go files in package
        TestImports  []string `json:",omitempty"` // imports from TestGoFiles
        XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
        XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
 }
 
+// AllFiles returns the names of all the files considered for the package.
+// This is used for sanity and security checks, so we include all files,
+// even IgnoredGoFiles, because some subcommands consider them.
+// The go/build package filtered others out (like foo_wrongGOARCH.s)
+// and that's OK.
+func (p *Package) AllFiles() []string {
+       return str.StringList(
+               p.GoFiles,
+               p.CgoFiles,
+               p.IgnoredGoFiles,
+               p.CFiles,
+               p.CXXFiles,
+               p.MFiles,
+               p.HFiles,
+               p.FFiles,
+               p.SFiles,
+               p.SwigFiles,
+               p.SwigCXXFiles,
+               p.SysoFiles,
+               p.TestGoFiles,
+               p.XTestGoFiles,
+       )
+}
+
 type PackageInternal struct {
        // Unexported fields are not part of the public API.
        Build        *build.Package
@@ -420,6 +449,9 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
                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 {
@@ -518,6 +550,13 @@ func isDir(path string) bool {
 // 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
        }
@@ -1010,22 +1049,8 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
        // To avoid problems on case-insensitive files, we reject any package
        // where two different input files have equal names under a case-insensitive
        // comparison.
-       f1, f2 := str.FoldDup(str.StringList(
-               p.GoFiles,
-               p.CgoFiles,
-               p.IgnoredGoFiles,
-               p.CFiles,
-               p.CXXFiles,
-               p.MFiles,
-               p.HFiles,
-               p.FFiles,
-               p.SFiles,
-               p.SysoFiles,
-               p.SwigFiles,
-               p.SwigCXXFiles,
-               p.TestGoFiles,
-               p.XTestGoFiles,
-       ))
+       inputs := p.AllFiles()
+       f1, f2 := str.FoldDup(inputs)
        if f1 != "" {
                p.Error = &PackageError{
                        ImportStack: stk.Copy(),
@@ -1034,6 +1059,37 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
                return
        }
 
+       // If first letter of input file is ASCII, it must be alphanumeric.
+       // This avoids files turning into flags when invoking commands,
+       // and other problems we haven't thought of yet.
+       // Also, _cgo_ files must be generated by us, not supplied.
+       // They are allowed to have //go:cgo_ldflag directives.
+       // The directory scan ignores files beginning with _,
+       // so we shouldn't see any _cgo_ files anyway, but just be safe.
+       for _, file := range inputs {
+               if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
+                       p.Error = &PackageError{
+                               ImportStack: stk.Copy(),
+                               Err:         fmt.Sprintf("invalid input file name %q", file),
+                       }
+                       return
+               }
+       }
+       if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
+               p.Error = &PackageError{
+                       ImportStack: stk.Copy(),
+                       Err:         fmt.Sprintf("invalid input directory name %q", name),
+               }
+               return
+       }
+       if !SafeArg(p.ImportPath) {
+               p.Error = &PackageError{
+                       ImportStack: stk.Copy(),
+                       Err:         fmt.Sprintf("invalid import path %q", p.ImportPath),
+               }
+               return
+       }
+
        // Build list of imported packages and full dependency list.
        imports := make([]*Package, 0, len(p.Imports))
        for i, path := range importPaths {
@@ -1160,6 +1216,22 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
        }
 }
 
+// SafeArg reports whether arg is a "safe" command-line argument,
+// meaning that when it appears in a command-line, it probably
+// doesn't have some special meaning other than its own name.
+// Obviously args beginning with - are not safe (they look like flags).
+// Less obviously, args beginning with @ are not safe (they look like
+// GNU binutils flagfile specifiers, sometimes called "response files").
+// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
+// We accept leading . _ and / as likely in file system paths.
+func SafeArg(name string) bool {
+       if name == "" {
+               return false
+       }
+       c := name[0]
+       return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
+}
+
 // LinkerDeps returns the list of linker-induced dependencies for main package p.
 func LinkerDeps(p *Package) []string {
        // Everything links runtime.
index e77e834cb23989888440f7c02b3c2ed94996f89c..978547079644789cd14b3058d4451afed77e5720 100644 (file)
@@ -662,6 +662,15 @@ func runTest(cmd *base.Command, args []string) {
                                        haveMatch = true
                                }
                        }
+
+                       // Silently ignore attempts to run coverage on
+                       // sync/atomic when using atomic coverage mode.
+                       // Atomic coverage mode uses sync/atomic, so
+                       // we can't also do coverage on it.
+                       if testCoverMode == "atomic" && p.Standard && p.ImportPath == "sync/atomic" {
+                               continue
+                       }
+
                        if haveMatch {
                                testCoverPkgs = append(testCoverPkgs, p)
                        }
@@ -894,7 +903,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
                t.ImportXtest = true
        }
 
-       if ptest != p && localCover {
+       if ptest != p {
                // We have made modifications to the package p being tested
                // and are rebuilding p (as ptest).
                // Arrange to rebuild all packages q such that
@@ -903,13 +912,6 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
                // Strictly speaking, the rebuild is only necessary if the
                // modifications to p change its export metadata, but
                // determining that is a bit tricky, so we rebuild always.
-               // TODO(rsc): Once we get export metadata changes
-               // handled properly, look into the expense of dropping
-               // "&& localCover" above.
-               //
-               // This will cause extra compilation, so for now we only do it
-               // when testCover is set. The conditions are more general, though,
-               // and we may find that we need to do it always in the future.
                recompileForTest(pmain, p, ptest, pxtest)
        }
 
index b58749827083ba7b0ad25932b4c842e416b5ea46..5527e90756d38aeda3faf81844a4f1dd10ff2560 100644 (file)
@@ -197,7 +197,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
        fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix)
        if len(p.CgoFiles)+len(p.SwigFiles) > 0 {
                fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo"))
-               cppflags, cflags, cxxflags, fflags, _ := b.CFlags(p)
+               cppflags, cflags, cxxflags, fflags, _, _ := b.CFlags(p)
                fmt.Fprintf(h, "CC=%q %q %q\n", b.ccExe(), cppflags, cflags)
                if len(p.CXXFiles)+len(p.SwigFiles) > 0 {
                        fmt.Fprintf(h, "CXX=%q %q\n", b.cxxExe(), cxxflags)
@@ -521,7 +521,14 @@ func (b *Builder) build(a *Action) (err error) {
        }
 
        // Prepare Go import config.
+       // We start it off with a comment so it can't be empty, so icfg.Bytes() below is never nil.
+       // It should never be empty anyway, but there have been bugs in the past that resulted
+       // in empty configs, which then unfortunately turn into "no config passed to compiler",
+       // and the compiler falls back to looking in pkg itself, which mostly works,
+       // except when it doesn't.
        var icfg bytes.Buffer
+       fmt.Fprintf(&icfg, "# import config\n")
+
        for i, raw := range a.Package.Internal.RawImports {
                final := a.Package.Imports[i]
                if final != raw {
@@ -938,28 +945,38 @@ func splitPkgConfigOutput(out []byte) []string {
 // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
 func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
        if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
+               for _, pkg := range pkgs {
+                       if !load.SafeArg(pkg) {
+                               return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
+                       }
+               }
                var out []byte
-               out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pkgs)
+               out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", "--", pkgs)
                if err != nil {
                        b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out))
                        b.Print(err.Error() + "\n")
-                       err = errPrintedOutput
-                       return
+                       return nil, nil, errPrintedOutput
                }
                if len(out) > 0 {
                        cflags = splitPkgConfigOutput(out)
+                       if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags); err != nil {
+                               return nil, nil, err
+                       }
                }
-               out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pkgs)
+               out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", "--", pkgs)
                if err != nil {
                        b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out))
                        b.Print(err.Error() + "\n")
-                       err = errPrintedOutput
-                       return
+                       return nil, nil, errPrintedOutput
                }
                if len(out) > 0 {
                        ldflags = strings.Fields(string(out))
+                       if err := checkLinkerFlags("CFLAGS", "pkg-config --cflags", ldflags); err != nil {
+                               return nil, nil, err
+                       }
                }
        }
+
        return
 }
 
@@ -1464,6 +1481,17 @@ func (b *Builder) processOutput(out []byte) string {
 // It returns the command output and any errors that occurred.
 func (b *Builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
        cmdline := str.StringList(cmdargs...)
+
+       for _, arg := range cmdline {
+               // GNU binutils commands, including gcc and gccgo, interpret an argument
+               // @foo anywhere in the command line (even following --) as meaning
+               // "read and insert arguments from the file named foo."
+               // Don't say anything that might be misinterpreted that way.
+               if strings.HasPrefix(arg, "@") {
+                       return nil, fmt.Errorf("invalid command-line argument %s in command: %s", arg, joinUnambiguously(cmdline))
+               }
+       }
+
        if cfg.BuildN || cfg.BuildX {
                var envcmdline string
                for _, e := range env {
@@ -1916,22 +1944,44 @@ func envList(key, def string) []string {
 }
 
 // CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
-func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
+func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string, err error) {
        defaults := "-g -O2"
 
-       cppflags = str.StringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
-       cflags = str.StringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
-       cxxflags = str.StringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
-       fflags = str.StringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
-       ldflags = str.StringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
+       if cppflags, err = buildFlags("CPPFLAGS", "", p.CgoCPPFLAGS, checkCompilerFlags); err != nil {
+               return
+       }
+       if cflags, err = buildFlags("CFLAGS", defaults, p.CgoCFLAGS, checkCompilerFlags); err != nil {
+               return
+       }
+       if cxxflags, err = buildFlags("CXXFLAGS", defaults, p.CgoCXXFLAGS, checkCompilerFlags); err != nil {
+               return
+       }
+       if fflags, err = buildFlags("FFLAGS", defaults, p.CgoFFLAGS, checkCompilerFlags); err != nil {
+               return
+       }
+       if ldflags, err = buildFlags("LDFLAGS", defaults, p.CgoLDFLAGS, checkLinkerFlags); err != nil {
+               return
+       }
+
        return
 }
 
+func buildFlags(name, defaults string, fromPackage []string, check func(string, string, []string) error) ([]string, error) {
+       if err := check(name, "#cgo "+name, fromPackage); err != nil {
+               return nil, err
+       }
+       return str.StringList(envList("CGO_"+name, defaults), fromPackage), nil
+}
+
 var cgoRe = regexp.MustCompile(`[/\\:]`)
 
 func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
        p := a.Package
-       cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.CFlags(p)
+       cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS, err := b.CFlags(p)
+       if err != nil {
+               return nil, nil, err
+       }
+
        cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
        cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
        // If we are compiling Objective-C code, then we need to link against libobjc
@@ -1981,6 +2031,12 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
        }
 
        // Update $CGO_LDFLAGS with p.CgoLDFLAGS.
+       // These flags are recorded in the generated _cgo_gotypes.go file
+       // using //go:cgo_ldflag directives, the compiler records them in the
+       // object file for the package, and then the Go linker passes them
+       // along to the host linker. At this point in the code, cgoLDFLAGS
+       // consists of the original $CGO_LDFLAGS (unchecked) and all the
+       // flags put together from source code (checked).
        var cgoenv []string
        if len(cgoLDFLAGS) > 0 {
                flags := make([]string, len(cgoLDFLAGS))
@@ -2272,7 +2328,11 @@ func (b *Builder) swigIntSize(objdir string) (intsize string, err error) {
 
 // Run SWIG on one SWIG input file.
 func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
-       cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.CFlags(p)
+       cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _, err := b.CFlags(p)
+       if err != nil {
+               return "", "", err
+       }
+
        var cflags []string
        if cxx {
                cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
diff --git a/libgo/go/cmd/go/internal/work/security.go b/libgo/go/cmd/go/internal/work/security.go
new file mode 100644 (file)
index 0000000..fee5bee
--- /dev/null
@@ -0,0 +1,160 @@
+// Copyright 2018 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.
+
+// Checking of compiler and linker flags.
+// We must avoid flags like -fplugin=, which can allow
+// arbitrary code execution during the build.
+// Do not make changes here without carefully
+// considering the implications.
+// (That's why the code is isolated in a file named security.go.)
+//
+// Note that -Wl,foo means split foo on commas and pass to
+// the linker, so that -Wl,-foo,bar means pass -foo bar to
+// the linker. Similarly -Wa,foo for the assembler and so on.
+// If any of these are permitted, the wildcard portion must
+// disallow commas.
+//
+// Note also that GNU binutils accept any argument @foo
+// as meaning "read more flags from the file foo", so we must
+// guard against any command-line argument beginning with @,
+// even things like "-I @foo".
+// We use load.SafeArg (which is even more conservative)
+// to reject these.
+//
+// Even worse, gcc -I@foo (one arg) turns into cc1 -I @foo (two args),
+// so although gcc doesn't expand the @foo, cc1 will.
+// So out of paranoia, we reject @ at the beginning of every
+// flag argument that might be split into its own argument.
+
+package work
+
+import (
+       "cmd/go/internal/load"
+       "fmt"
+       "os"
+       "regexp"
+)
+
+var re = regexp.MustCompile
+
+var validCompilerFlags = []*regexp.Regexp{
+       re(`-D([A-Za-z_].*)`),
+       re(`-I([^@\-].*)`),
+       re(`-O`),
+       re(`-O([^@\-].*)`),
+       re(`-W`),
+       re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
+       re(`-f(no-)?objc-arc`),
+       re(`-f(no-)?omit-frame-pointer`),
+       re(`-f(no-)?(pic|PIC|pie|PIE)`),
+       re(`-f(no-)?split-stack`),
+       re(`-f(no-)?stack-(.+)`),
+       re(`-f(no-)?strict-aliasing`),
+       re(`-fsanitize=(.+)`),
+       re(`-g([^@\-].*)?`),
+       re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
+       re(`-m(no-)?stack-(.+)`),
+       re(`-mmacosx-(.+)`),
+       re(`-mnop-fun-dllimport`),
+       re(`-pthread`),
+       re(`-std=([^@\-].*)`),
+       re(`-x([^@\-].*)`),
+}
+
+var validCompilerFlagsWithNextArg = []string{
+       "-D",
+       "-I",
+       "-framework",
+       "-x",
+}
+
+var validLinkerFlags = []*regexp.Regexp{
+       re(`-F([^@\-].*)`),
+       re(`-l([^@\-].*)`),
+       re(`-L([^@\-].*)`),
+       re(`-f(no-)?(pic|PIC|pie|PIE)`),
+       re(`-fsanitize=([^@\-].*)`),
+       re(`-g([^@\-].*)?`),
+       re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
+       re(`-(pic|PIC|pie|PIE)`),
+       re(`-pthread`),
+
+       // Note that any wildcards in -Wl need to exclude comma,
+       // since -Wl splits its argument at commas and passes
+       // them all to the linker uninterpreted. Allowing comma
+       // in a wildcard would allow tunnelling arbitrary additional
+       // linker arguments through one of these.
+       re(`-Wl,-rpath,([^,@\-][^,]+)`),
+       re(`-Wl,--(no-)?warn-([^,]+)`),
+
+       re(`[a-zA-Z0-9_].*\.(o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
+}
+
+var validLinkerFlagsWithNextArg = []string{
+       "-F",
+       "-l",
+       "-L",
+       "-framework",
+}
+
+func checkCompilerFlags(name, source string, list []string) error {
+       return checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg)
+}
+
+func checkLinkerFlags(name, source string, list []string) error {
+       return checkFlags(name, source, list, validLinkerFlags, validLinkerFlagsWithNextArg)
+}
+
+func checkFlags(name, source string, list []string, valid []*regexp.Regexp, validNext []string) error {
+       // Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc.
+       var (
+               allow    *regexp.Regexp
+               disallow *regexp.Regexp
+       )
+       if env := os.Getenv("CGO_" + name + "_ALLOW"); env != "" {
+               r, err := regexp.Compile(env)
+               if err != nil {
+                       return fmt.Errorf("parsing $CGO_%s_ALLOW: %v", name, err)
+               }
+               allow = r
+       }
+       if env := os.Getenv("CGO_" + name + "_DISALLOW"); env != "" {
+               r, err := regexp.Compile(env)
+               if err != nil {
+                       return fmt.Errorf("parsing $CGO_%s_DISALLOW: %v", name, err)
+               }
+               disallow = r
+       }
+
+Args:
+       for i := 0; i < len(list); i++ {
+               arg := list[i]
+               if disallow != nil && disallow.FindString(arg) == arg {
+                       goto Bad
+               }
+               if allow != nil && allow.FindString(arg) == arg {
+                       continue Args
+               }
+               for _, re := range valid {
+                       if re.FindString(arg) == arg { // must be complete match
+                               continue Args
+                       }
+               }
+               for _, x := range validNext {
+                       if arg == x {
+                               if i+1 < len(list) && load.SafeArg(list[i+1]) {
+                                       i++
+                                       continue Args
+                               }
+                               if i+1 < len(list) {
+                                       return fmt.Errorf("invalid flag in %s: %s %s", source, arg, list[i+1])
+                               }
+                               return fmt.Errorf("invalid flag in %s: %s without argument", source, arg)
+                       }
+               }
+       Bad:
+               return fmt.Errorf("invalid flag in %s: %s", source, arg)
+       }
+       return nil
+}
diff --git a/libgo/go/cmd/go/internal/work/security_test.go b/libgo/go/cmd/go/internal/work/security_test.go
new file mode 100644 (file)
index 0000000..739ab5a
--- /dev/null
@@ -0,0 +1,240 @@
+// Copyright 2018 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 work
+
+import (
+       "os"
+       "testing"
+)
+
+var goodCompilerFlags = [][]string{
+       {"-DFOO"},
+       {"-Dfoo=bar"},
+       {"-I/"},
+       {"-I/etc/passwd"},
+       {"-I."},
+       {"-O"},
+       {"-O2"},
+       {"-Osmall"},
+       {"-W"},
+       {"-Wall"},
+       {"-fobjc-arc"},
+       {"-fno-objc-arc"},
+       {"-fomit-frame-pointer"},
+       {"-fno-omit-frame-pointer"},
+       {"-fpic"},
+       {"-fno-pic"},
+       {"-fPIC"},
+       {"-fno-PIC"},
+       {"-fpie"},
+       {"-fno-pie"},
+       {"-fPIE"},
+       {"-fno-PIE"},
+       {"-fsplit-stack"},
+       {"-fno-split-stack"},
+       {"-fstack-xxx"},
+       {"-fno-stack-xxx"},
+       {"-fsanitize=hands"},
+       {"-g"},
+       {"-ggdb"},
+       {"-march=souza"},
+       {"-mcpu=123"},
+       {"-mfpu=123"},
+       {"-mtune=happybirthday"},
+       {"-mstack-overflow"},
+       {"-mno-stack-overflow"},
+       {"-mmacosx-version"},
+       {"-mnop-fun-dllimport"},
+       {"-pthread"},
+       {"-std=c99"},
+       {"-xc"},
+       {"-D", "FOO"},
+       {"-D", "foo=bar"},
+       {"-I", "."},
+       {"-I", "/etc/passwd"},
+       {"-I", "世界"},
+       {"-framework", "Chocolate"},
+       {"-x", "c"},
+}
+
+var badCompilerFlags = [][]string{
+       {"-D@X"},
+       {"-D-X"},
+       {"-I@dir"},
+       {"-I-dir"},
+       {"-O@1"},
+       {"-Wa,-foo"},
+       {"-W@foo"},
+       {"-g@gdb"},
+       {"-g-gdb"},
+       {"-march=@dawn"},
+       {"-march=-dawn"},
+       {"-std=@c99"},
+       {"-std=-c99"},
+       {"-x@c"},
+       {"-x-c"},
+       {"-D", "@foo"},
+       {"-D", "-foo"},
+       {"-I", "@foo"},
+       {"-I", "-foo"},
+       {"-framework", "-Caffeine"},
+       {"-framework", "@Home"},
+       {"-x", "--c"},
+       {"-x", "@obj"},
+}
+
+func TestCheckCompilerFlags(t *testing.T) {
+       for _, f := range goodCompilerFlags {
+               if err := checkCompilerFlags("test", "test", f); err != nil {
+                       t.Errorf("unexpected error for %q: %v", f, err)
+               }
+       }
+       for _, f := range badCompilerFlags {
+               if err := checkCompilerFlags("test", "test", f); err == nil {
+                       t.Errorf("missing error for %q", f)
+               }
+       }
+}
+
+var goodLinkerFlags = [][]string{
+       {"-Fbar"},
+       {"-lbar"},
+       {"-Lbar"},
+       {"-fpic"},
+       {"-fno-pic"},
+       {"-fPIC"},
+       {"-fno-PIC"},
+       {"-fpie"},
+       {"-fno-pie"},
+       {"-fPIE"},
+       {"-fno-PIE"},
+       {"-fsanitize=hands"},
+       {"-g"},
+       {"-ggdb"},
+       {"-march=souza"},
+       {"-mcpu=123"},
+       {"-mfpu=123"},
+       {"-mtune=happybirthday"},
+       {"-pic"},
+       {"-pthread"},
+       {"-Wl,-rpath,foo"},
+       {"-Wl,-rpath,$ORIGIN/foo"},
+       {"-Wl,--warn-error"},
+       {"-Wl,--no-warn-error"},
+       {"foo.so"},
+       {"_世界.dll"},
+       {"libcgosotest.dylib"},
+       {"-F", "framework"},
+       {"-l", "."},
+       {"-l", "/etc/passwd"},
+       {"-l", "世界"},
+       {"-L", "framework"},
+       {"-framework", "Chocolate"},
+}
+
+var badLinkerFlags = [][]string{
+       {"-DFOO"},
+       {"-Dfoo=bar"},
+       {"-O"},
+       {"-O2"},
+       {"-Osmall"},
+       {"-W"},
+       {"-Wall"},
+       {"-fobjc-arc"},
+       {"-fno-objc-arc"},
+       {"-fomit-frame-pointer"},
+       {"-fno-omit-frame-pointer"},
+       {"-fsplit-stack"},
+       {"-fno-split-stack"},
+       {"-fstack-xxx"},
+       {"-fno-stack-xxx"},
+       {"-mstack-overflow"},
+       {"-mno-stack-overflow"},
+       {"-mmacosx-version"},
+       {"-mnop-fun-dllimport"},
+       {"-std=c99"},
+       {"-xc"},
+       {"-D", "FOO"},
+       {"-D", "foo=bar"},
+       {"-I", "FOO"},
+       {"-L", "@foo"},
+       {"-L", "-foo"},
+       {"-x", "c"},
+       {"-D@X"},
+       {"-D-X"},
+       {"-I@dir"},
+       {"-I-dir"},
+       {"-O@1"},
+       {"-Wa,-foo"},
+       {"-W@foo"},
+       {"-g@gdb"},
+       {"-g-gdb"},
+       {"-march=@dawn"},
+       {"-march=-dawn"},
+       {"-std=@c99"},
+       {"-std=-c99"},
+       {"-x@c"},
+       {"-x-c"},
+       {"-D", "@foo"},
+       {"-D", "-foo"},
+       {"-I", "@foo"},
+       {"-I", "-foo"},
+       {"-l", "@foo"},
+       {"-l", "-foo"},
+       {"-framework", "-Caffeine"},
+       {"-framework", "@Home"},
+       {"-x", "--c"},
+       {"-x", "@obj"},
+       {"-Wl,-rpath,@foo"},
+}
+
+func TestCheckLinkerFlags(t *testing.T) {
+       for _, f := range goodLinkerFlags {
+               if err := checkLinkerFlags("test", "test", f); err != nil {
+                       t.Errorf("unexpected error for %q: %v", f, err)
+               }
+       }
+       for _, f := range badLinkerFlags {
+               if err := checkLinkerFlags("test", "test", f); err == nil {
+                       t.Errorf("missing error for %q", f)
+               }
+       }
+}
+
+func TestCheckFlagAllowDisallow(t *testing.T) {
+       if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil {
+               t.Fatalf("missing error for -disallow")
+       }
+       os.Setenv("CGO_TEST_ALLOW", "-disallo")
+       if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil {
+               t.Fatalf("missing error for -disallow with CGO_TEST_ALLOW=-disallo")
+       }
+       os.Setenv("CGO_TEST_ALLOW", "-disallow")
+       if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err != nil {
+               t.Fatalf("unexpected error for -disallow with CGO_TEST_ALLOW=-disallow: %v", err)
+       }
+       os.Unsetenv("CGO_TEST_ALLOW")
+
+       if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err != nil {
+               t.Fatalf("unexpected error for -Wall: %v", err)
+       }
+       os.Setenv("CGO_TEST_DISALLOW", "-Wall")
+       if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil {
+               t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall")
+       }
+       os.Setenv("CGO_TEST_ALLOW", "-Wall") // disallow wins
+       if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil {
+               t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall and CGO_TEST_ALLOW=-Wall")
+       }
+
+       os.Setenv("CGO_TEST_ALLOW", "-fplugin.*")
+       os.Setenv("CGO_TEST_DISALLOW", "-fplugin=lint.so")
+       if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=faster.so"}); err != nil {
+               t.Fatalf("unexpected error for -fplugin=faster.so: %v", err)
+       }
+       if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=lint.so"}); err == nil {
+               t.Fatalf("missing error for -fplugin=lint.so: %v", err)
+       }
+}
index 19a3a4f7c9aa2bcaa23c559f93d80e101a52bf1e..1e54b4cf2cf1759f4fc6dedc9e0fd18ada651d19 100644 (file)
@@ -379,6 +379,10 @@ type Rows interface {
        // size as the Columns() are wide.
        //
        // Next should return io.EOF when there are no more rows.
+       //
+       // The dest should not be written to outside of Next. Care
+       // should be taken when closing Rows not to modify
+       // a buffer held in dest.
        Next(dest []Value) error
 }
 
index e795412de01c97c7cc4faf2d6d3cbe106713375a..abb8d40fc022ed5c492e2709bdd1ec82b8fcccac 100644 (file)
@@ -1020,11 +1020,6 @@ func (rc *rowsCursor) touchMem() {
 }
 
 func (rc *rowsCursor) Close() error {
-       if !rc.closed {
-               for _, bs := range rc.bytesClone {
-                       bs[0] = 255 // first byte corrupted
-               }
-       }
        rc.touchMem()
        rc.parentMem.touchMem()
        rc.closed = true
index 8137eff82b4ae1511bb63b11de4ff41e90b54b90..ae6bf7102e36c907fdd293ffee615ff6fb5c8f0f 100644 (file)
@@ -663,43 +663,6 @@ func TestPoolExhaustOnCancel(t *testing.T) {
        }
 }
 
-func TestByteOwnership(t *testing.T) {
-       db := newTestDB(t, "people")
-       defer closeDB(t, db)
-       rows, err := db.Query("SELECT|people|name,photo|")
-       if err != nil {
-               t.Fatalf("Query: %v", err)
-       }
-       type row struct {
-               name  []byte
-               photo RawBytes
-       }
-       got := []row{}
-       for rows.Next() {
-               var r row
-               err = rows.Scan(&r.name, &r.photo)
-               if err != nil {
-                       t.Fatalf("Scan: %v", err)
-               }
-               got = append(got, r)
-       }
-       corruptMemory := []byte("\xffPHOTO")
-       want := []row{
-               {name: []byte("Alice"), photo: corruptMemory},
-               {name: []byte("Bob"), photo: corruptMemory},
-               {name: []byte("Chris"), photo: corruptMemory},
-       }
-       if !reflect.DeepEqual(got, want) {
-               t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
-       }
-
-       var photo RawBytes
-       err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo)
-       if err == nil {
-               t.Error("want error scanning into RawBytes from QueryRow")
-       }
-}
-
 func TestRowsColumns(t *testing.T) {
        db := newTestDB(t, "people")
        defer closeDB(t, db)
@@ -3192,8 +3155,11 @@ func TestIssue18429(t *testing.T) {
                        // reported.
                        rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|")
                        if rows != nil {
+                               var name string
                                // Call Next to test Issue 21117 and check for races.
                                for rows.Next() {
+                                       // Scan the buffer so it is read and checked for races.
+                                       rows.Scan(&name)
                                }
                                rows.Close()
                        }
index e14a304f2fac4d206529dbc8766f057de3d59f5f..6f9838b55b92680ae590a5680bdc38e9b83c62ae 100644 (file)
@@ -302,7 +302,7 @@ var pkgDeps = map[string][]string{
        "os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
 
        // Internal package used only for testing.
-       "os/signal/internal/pty": {"CGO", "fmt", "os"},
+       "os/signal/internal/pty": {"CGO", "fmt", "os", "syscall"},
 
        // Basic networking.
        // Because net must be used by any package that wants to
index 52a34433233ef608e9a27457ffc705b254a878d0..299910de284e77324fcde27e31c3b1fb303a788b 100644 (file)
@@ -62,8 +62,6 @@ var importablePackages = [...]string{
        "encoding/pem",
        "encoding/xml",
        "errors",
-       "exp/proxy",
-       "exp/terminal",
        "expvar",
        "flag",
        "fmt",
@@ -114,8 +112,6 @@ var importablePackages = [...]string{
        "net/smtp",
        "net/textproto",
        "net/url",
-       "old/regexp",
-       "old/template",
        "os/exec",
        "os",
        "os/signal",
index dfb092055021f3956311ea93907e667f6dd4367e..516e557cfd29816ac1904dc577bbd5bec9ec22d9 100644 (file)
@@ -20,7 +20,7 @@ func maxListenerBacklog() int {
        case "darwin":
                n, err = syscall.SysctlUint32("kern.ipc.somaxconn")
        case "freebsd":
-               n, err = syscall.SysctlUint32("kern.ipc.acceptqueue")
+               n, err = syscall.SysctlUint32("kern.ipc.soacceptqueue")
        case "netbsd":
                // NOTE: NetBSD has no somaxconn-like kernel state so far
        case "openbsd":
index b3f60b62d0379b9653490a948b8df09bee95e6ad..a7f8710b955db572679762e03ee3c99ec8a69fe5 100644 (file)
@@ -88,6 +88,11 @@ func FindProcess(pid int) (*Process, error) {
 // specified by name, argv and attr. The argv slice will become os.Args in the
 // new process, so it normally starts with the program name.
 //
+// If the calling goroutine has locked the operating system thread
+// with runtime.LockOSThread and modified any inheritable OS-level
+// thread state (for example, Linux or Plan 9 name spaces), the new
+// process will inherit the caller's thread state.
+//
 // StartProcess is a low-level interface. The os/exec package provides
 // higher-level interfaces.
 //
index 8a49fe3b58eb68889225e8395360348859f0beae..5ef9540141ef0e7bba36b6b97bc3e1c7de81b92c 100644 (file)
@@ -293,6 +293,11 @@ func (c *Cmd) closeDescriptors(closers []io.Closer) {
 //
 // If the command starts but does not complete successfully, the error is of
 // type *ExitError. Other error types may be returned for other situations.
+//
+// If the calling goroutine has locked the operating system thread
+// with runtime.LockOSThread and modified any inheritable OS-level
+// thread state (for example, Linux or Plan 9 name spaces), the new
+// process will inherit the caller's thread state.
 func (c *Cmd) Run() error {
        if err := c.Start(); err != nil {
                return err
index 1c3480cffc5ff580b3d0a1c012cd417d89f38036..e52d19ac30cadba254a2fc38949058c107466b30 100644 (file)
@@ -33,21 +33,35 @@ func close(int32) int32
 
 const _O_RDWR = 2
 
+type PtyError struct {
+       FuncName    string
+       ErrorString string
+       Errno       syscall.Errno
+}
+
+func ptyError(name string, err error) *PtyError {
+       return &PtyError{name, err.Error(), err.(syscall.Errno)}
+}
+
+func (e *PtyError) Error() string {
+       return fmt.Sprintf("%s: %s", e.FuncName, e.ErrorString)
+}
+
 // Open returns a master pty and the name of the linked slave tty.
 func Open() (master *os.File, slave string, err error) {
        m := posix_openpt(_O_RDWR)
        if m < 0 {
-               return nil, "", fmt.Errorf("posix_openpt: %v", syscall.GetErrno())
+               return nil, "", ptyError("posix_openpt", syscall.GetErrno())
        }
        if grantpt(m) < 0 {
                errno := syscall.GetErrno()
                close(m)
-               return nil, "", fmt.Errorf("grantpt: %v", errno)
+               return nil, "", ptyError("grantpt", errno)
        }
        if unlockpt(m) < 0 {
                errno := syscall.GetErrno()
                close(m)
-               return nil, "", fmt.Errorf("unlockpt: %v", errno)
+               return nil, "", ptyError("unlockpt", errno)
        }
        p := ptsname(m)
        s := (*[32000]byte)(unsafe.Pointer(p))[:]
index 27707fadcee4b60ff8ea8a658011163af7e3812e..84a2a08ce9b6e5a11e072f581b72cbc890e40414 100644 (file)
@@ -72,6 +72,10 @@ func TestTerminalSignal(t *testing.T) {
 
        master, sname, err := pty.Open()
        if err != nil {
+               ptyErr := err.(*pty.PtyError)
+               if ptyErr.FuncName == "posix_openpt" && ptyErr.Errno == syscall.EACCES {
+                       t.Skip("posix_openpt failed with EACCES, assuming chroot and skipping")
+               }
                t.Fatal(err)
        }
        defer master.Close()
index 35321470425a79cf91d707c6aff920883c3a718f..6688b3cbf6be30795617c1db0e0016f1cd41bdf7 100644 (file)
@@ -493,3 +493,24 @@ func TestSigStackSwapping(t *testing.T) {
                t.Errorf("expected %q got %v", want, got)
        }
 }
+
+func TestCgoTracebackSigpanic(t *testing.T) {
+       // Test unwinding over a sigpanic in C code without a C
+       // symbolizer. See issue #23576.
+       if runtime.GOOS == "windows" {
+               // On Windows if we get an exception in C code, we let
+               // the Windows exception handler unwind it, rather
+               // than injecting a sigpanic.
+               t.Skip("no sigpanic in C on windows")
+       }
+       t.Parallel()
+       got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
+       want := "runtime.sigpanic"
+       if !strings.Contains(got, want) {
+               t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
+       }
+       nowant := "unexpected return pc"
+       if strings.Contains(got, nowant) {
+               t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
+       }
+}
diff --git a/libgo/go/runtime/testdata/testprogcgo/sigpanic.go b/libgo/go/runtime/testdata/testprogcgo/sigpanic.go
new file mode 100644 (file)
index 0000000..cb46030
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 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
+
+// This program will crash.
+// We want to test unwinding from sigpanic into C code (without a C symbolizer).
+
+/*
+#cgo CFLAGS: -O0
+
+char *pnil;
+
+static int f1(void) {
+       *pnil = 0;
+       return 0;
+}
+*/
+import "C"
+
+func init() {
+       register("TracebackSigpanic", TracebackSigpanic)
+}
+
+func TracebackSigpanic() {
+       C.f1()
+}
index f7609293cea8a6d6942f1998bac9f31d7b6caf69..d174ebd9cfeedc5a589ad9268609e21b39998764 100644 (file)
@@ -110,12 +110,6 @@ data, defined in detail in the corresponding sections that follow.
                T0 is executed; otherwise, dot is set to the successive elements
                of the array, slice, or map and T1 is executed.
 
-       {{break}}
-               Break out of the surrounding range loop.
-
-       {{continue}}
-               Begin the next iteration of the surrounding range loop.
-
        {{template "name"}}
                The template with the specified name is executed with nil data.
 
index 90810090e296de5f1b2633ad67a6ba48a5b3bc75..2923dd9d83fb4d01d72b9f9c365c7ff8ff38134e 100644 (file)
@@ -27,12 +27,11 @@ const maxExecDepth = 1000
 // template so that multiple executions of the same template
 // can execute in parallel.
 type state struct {
-       tmpl       *Template
-       wr         io.Writer
-       node       parse.Node // current node, for errors.
-       vars       []variable // push-down stack of variable values.
-       depth      int        // the height of the stack of executing templates.
-       rangeDepth int        // nesting level of range loops.
+       tmpl  *Template
+       wr    io.Writer
+       node  parse.Node // current node, for errors
+       vars  []variable // push-down stack of variable values.
+       depth int        // the height of the stack of executing templates.
 }
 
 // variable holds the dynamic value of a variable such as $, $x etc.
@@ -223,17 +222,9 @@ func (t *Template) DefinedTemplates() string {
        return s
 }
 
-type rangeControl int8
-
-const (
-       rangeNone     rangeControl = iota // no action.
-       rangeBreak                        // break out of range.
-       rangeContinue                     // continues next range iteration.
-)
-
 // Walk functions step through the major pieces of the template structure,
 // generating output as they go.
-func (s *state) walk(dot reflect.Value, node parse.Node) rangeControl {
+func (s *state) walk(dot reflect.Value, node parse.Node) {
        s.at(node)
        switch node := node.(type) {
        case *parse.ActionNode:
@@ -244,15 +235,13 @@ func (s *state) walk(dot reflect.Value, node parse.Node) rangeControl {
                        s.printValue(node, val)
                }
        case *parse.IfNode:
-               return s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
+               s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
        case *parse.ListNode:
                for _, node := range node.Nodes {
-                       if c := s.walk(dot, node); c != rangeNone {
-                               return c
-                       }
+                       s.walk(dot, node)
                }
        case *parse.RangeNode:
-               return s.walkRange(dot, node)
+               s.walkRange(dot, node)
        case *parse.TemplateNode:
                s.walkTemplate(dot, node)
        case *parse.TextNode:
@@ -260,26 +249,15 @@ func (s *state) walk(dot reflect.Value, node parse.Node) rangeControl {
                        s.writeError(err)
                }
        case *parse.WithNode:
-               return s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
-       case *parse.BreakNode:
-               if s.rangeDepth == 0 {
-                       s.errorf("invalid break outside of range")
-               }
-               return rangeBreak
-       case *parse.ContinueNode:
-               if s.rangeDepth == 0 {
-                       s.errorf("invalid continue outside of range")
-               }
-               return rangeContinue
+               s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
        default:
                s.errorf("unknown node: %s", node)
        }
-       return rangeNone
 }
 
 // walkIfOrWith walks an 'if' or 'with' node. The two control structures
 // are identical in behavior except that 'with' sets dot.
-func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) rangeControl {
+func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
        defer s.pop(s.mark())
        val := s.evalPipeline(dot, pipe)
        truth, ok := isTrue(val)
@@ -288,14 +266,13 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.
        }
        if truth {
                if typ == parse.NodeWith {
-                       return s.walk(val, list)
+                       s.walk(val, list)
                } else {
-                       return s.walk(dot, list)
+                       s.walk(dot, list)
                }
        } else if elseList != nil {
-               return s.walk(dot, elseList)
+               s.walk(dot, elseList)
        }
-       return rangeNone
 }
 
 // IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
@@ -333,14 +310,13 @@ func isTrue(val reflect.Value) (truth, ok bool) {
        return truth, true
 }
 
-func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
+func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
        s.at(r)
        defer s.pop(s.mark())
        val, _ := indirect(s.evalPipeline(dot, r.Pipe))
        // mark top of stack before any variables in the body are pushed.
        mark := s.mark()
-       s.rangeDepth++
-       oneIteration := func(index, elem reflect.Value) rangeControl {
+       oneIteration := func(index, elem reflect.Value) {
                // Set top var (lexically the second if there are two) to the element.
                if len(r.Pipe.Decl) > 0 {
                        s.setVar(1, elem)
@@ -349,9 +325,8 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
                if len(r.Pipe.Decl) > 1 {
                        s.setVar(2, index)
                }
-               ctrl := s.walk(elem, r.List)
+               s.walk(elem, r.List)
                s.pop(mark)
-               return ctrl
        }
        switch val.Kind() {
        case reflect.Array, reflect.Slice:
@@ -359,23 +334,17 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
                        break
                }
                for i := 0; i < val.Len(); i++ {
-                       if ctrl := oneIteration(reflect.ValueOf(i), val.Index(i)); ctrl == rangeBreak {
-                               break
-                       }
+                       oneIteration(reflect.ValueOf(i), val.Index(i))
                }
-               s.rangeDepth--
-               return rangeNone
+               return
        case reflect.Map:
                if val.Len() == 0 {
                        break
                }
                for _, key := range sortKeys(val.MapKeys()) {
-                       if ctrl := oneIteration(key, val.MapIndex(key)); ctrl == rangeBreak {
-                               break
-                       }
+                       oneIteration(key, val.MapIndex(key))
                }
-               s.rangeDepth--
-               return rangeNone
+               return
        case reflect.Chan:
                if val.IsNil() {
                        break
@@ -386,25 +355,20 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
                        if !ok {
                                break
                        }
-                       if ctrl := oneIteration(reflect.ValueOf(i), elem); ctrl == rangeBreak {
-                               break
-                       }
+                       oneIteration(reflect.ValueOf(i), elem)
                }
                if i == 0 {
                        break
                }
-               s.rangeDepth--
-               return rangeNone
+               return
        case reflect.Invalid:
                break // An invalid value is likely a nil map, etc. and acts like an empty map.
        default:
                s.errorf("range can't iterate over %v", val)
        }
-       s.rangeDepth--
        if r.ElseList != nil {
-               return s.walk(dot, r.ElseList)
+               s.walk(dot, r.ElseList)
        }
-       return rangeNone
 }
 
 func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
index 79b504f8a4d02001f78e5d717540e979ad3e20d0..d0cda6bd625da787d8dd41fb204ff79ae392fbce 100644 (file)
@@ -513,10 +513,6 @@ var execTests = []execTest{
        {"declare in range", "{{range $x := .PSI}}<{{$foo:=$x}}{{$x}}>{{end}}", "<21><22><23>", tVal, true},
        {"range count", `{{range $i, $x := count 5}}[{{$i}}]{{$x}}{{end}}`, "[0]a[1]b[2]c[3]d[4]e", tVal, true},
        {"range nil count", `{{range $i, $x := count 0}}{{else}}empty{{end}}`, "empty", tVal, true},
-       {"range quick break", `{{range .SI}}{{break}}{{.}}{{end}}`, "", tVal, true},
-       {"range break after two", `{{range $i, $x := .SI}}{{if ge $i 2}}{{break}}{{end}}{{.}}{{end}}`, "34", tVal, true},
-       {"range continue", `{{range .SI}}{{continue}}{{.}}{{end}}`, "", tVal, true},
-       {"range continue condition", `{{range .SI}}{{if eq . 3 }}{{continue}}{{end}}{{.}}{{end}}`, "45", tVal, true},
 
        // Cute examples.
        {"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true},
index da766cc7c32be8b2c29de1a7377eccc4ec57408b..e112cb7714a422a58fd824e751a8a569deda9e88 100644 (file)
@@ -60,8 +60,6 @@ const (
        // Keywords appear after all the rest.
        itemKeyword  // used only to delimit the keywords
        itemBlock    // block keyword
-       itemBreak    // break keyword
-       itemContinue // continue keyword
        itemDot      // the cursor, spelled '.'
        itemDefine   // define keyword
        itemElse     // else keyword
@@ -76,8 +74,6 @@ const (
 var key = map[string]itemType{
        ".":        itemDot,
        "block":    itemBlock,
-       "break":    itemBreak,
-       "continue": itemContinue,
        "define":   itemDefine,
        "else":     itemElse,
        "end":      itemEnd,
index ca7c3f64bc7701c1054635e10611ddc99b83b0cb..cb01cd98b6ab2263618a5feec888e8bfc58807d5 100644 (file)
@@ -192,7 +192,7 @@ var lexTests = []lexTest{
                tRight,
                tEOF,
        }},
-       {"keywords", "{{range if else end with break continue}}", []item{
+       {"keywords", "{{range if else end with}}", []item{
                tLeft,
                mkItem(itemRange, "range"),
                tSpace,
@@ -203,10 +203,6 @@ var lexTests = []lexTest{
                mkItem(itemEnd, "end"),
                tSpace,
                mkItem(itemWith, "with"),
-               tSpace,
-               mkItem(itemBreak, "break"),
-               tSpace,
-               mkItem(itemContinue, "continue"),
                tRight,
                tEOF,
        }},
index 7e16349b31eabd62b36598b09cae87a6301d9ed7..55ff46c17ab28e84875f70758cc41796651fa53e 100644 (file)
@@ -69,8 +69,6 @@ const (
        NodeTemplate                   // A template invocation action.
        NodeVariable                   // A $ variable.
        NodeWith                       // A with action.
-       NodeBreak                      // A break action.
-       NodeContinue                   // A continue action.
 )
 
 // Nodes.
@@ -798,68 +796,6 @@ func (r *RangeNode) Copy() Node {
        return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
 }
 
-// BreakNode represents a {{break}} action.
-type BreakNode struct {
-       NodeType
-       Pos
-       tr *Tree
-}
-
-func (t *Tree) newBreak(pos Pos) *BreakNode {
-       return &BreakNode{NodeType: NodeBreak, Pos: pos, tr: t}
-}
-
-func (b *BreakNode) Type() NodeType {
-       return b.NodeType
-}
-
-func (b *BreakNode) String() string {
-       return "{{break}}"
-}
-
-func (b *BreakNode) Copy() Node {
-       return b.tr.newBreak(b.Pos)
-}
-
-func (b *BreakNode) Position() Pos {
-       return b.Pos
-}
-
-func (b *BreakNode) tree() *Tree {
-       return b.tr
-}
-
-// ContinueNode represents a {{continue}} action.
-type ContinueNode struct {
-       NodeType
-       Pos
-       tr *Tree
-}
-
-func (t *Tree) newContinue(pos Pos) *ContinueNode {
-       return &ContinueNode{NodeType: NodeContinue, Pos: pos, tr: t}
-}
-
-func (c *ContinueNode) Type() NodeType {
-       return c.NodeType
-}
-
-func (c *ContinueNode) String() string {
-       return "{{continue}}"
-}
-
-func (c *ContinueNode) Copy() Node {
-       return c.tr.newContinue(c.Pos)
-}
-
-func (c *ContinueNode) Position() Pos {
-       return c.Pos
-}
-
-func (c *ContinueNode) tree() *Tree {
-       return c.tr
-}
-
 // WithNode represents a {{with}} action and its commands.
 type WithNode struct {
        BranchNode
index ad9c05197895bafbb36f9d963baed346d7dd0725..a91a544ce016f2c5446c441dcc30a3abf5d39966 100644 (file)
@@ -23,13 +23,12 @@ type Tree struct {
        Root      *ListNode // top-level root of the tree.
        text      string    // text parsed to create the template (or its parent)
        // Parsing only; cleared after parse.
-       funcs      []map[string]interface{}
-       lex        *lexer
-       token      [3]item // three-token lookahead for parser.
-       peekCount  int
-       vars       []string // variables defined at the moment.
-       treeSet    map[string]*Tree
-       rangeDepth int // nesting level of range loops.
+       funcs     []map[string]interface{}
+       lex       *lexer
+       token     [3]item // three-token lookahead for parser.
+       peekCount int
+       vars      []string // variables defined at the moment.
+       treeSet   map[string]*Tree
 }
 
 // Copy returns a copy of the Tree. Any parsing state is discarded.
@@ -220,7 +219,6 @@ func (t *Tree) stopParse() {
        t.vars = nil
        t.funcs = nil
        t.treeSet = nil
-       t.rangeDepth = 0
 }
 
 // Parse parses the template definition string to construct a representation of
@@ -375,10 +373,6 @@ func (t *Tree) action() (n Node) {
                return t.templateControl()
        case itemWith:
                return t.withControl()
-       case itemBreak:
-               return t.breakControl()
-       case itemContinue:
-               return t.continueControl()
        }
        t.backup()
        token := t.peek()
@@ -459,13 +453,7 @@ func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int
        defer t.popVars(len(t.vars))
        pipe = t.pipeline(context)
        var next Node
-       if context == "range" {
-               t.rangeDepth++
-       }
        list, next = t.itemList()
-       if context == "range" {
-               t.rangeDepth--
-       }
        switch next.Type() {
        case nodeEnd: //done
        case nodeElse:
@@ -510,26 +498,6 @@ func (t *Tree) rangeControl() Node {
        return t.newRange(t.parseControl(false, "range"))
 }
 
-// Break:
-//     {{break}}
-// Break keyword is past.
-func (t *Tree) breakControl() Node {
-       if t.rangeDepth == 0 {
-               t.errorf("unexpected break outside of range")
-       }
-       return t.newBreak(t.expect(itemRightDelim, "break").pos)
-}
-
-// Continue:
-//     {{continue}}
-// Continue keyword is past.
-func (t *Tree) continueControl() Node {
-       if t.rangeDepth == 0 {
-               t.errorf("unexpected continue outside of range")
-       }
-       return t.newContinue(t.expect(itemRightDelim, "continue").pos)
-}
-
 // With:
 //     {{with pipeline}} itemList {{end}}
 //     {{with pipeline}} itemList {{else}} itemList {{end}}
index aade33ea48e98b5e34e3ed503f06f7e363010c1b..81f14aca986cdcb8774f0c2562cc388bf6a4bb16 100644 (file)
@@ -218,12 +218,6 @@ var parseTests = []parseTest{
                `{{range $x := .SI}}{{.}}{{end}}`},
        {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
                `{{range $x, $y := .SI}}{{.}}{{end}}`},
-       {"range []int with break", "{{range .SI}}{{break}}{{.}}{{end}}", noError,
-               `{{range .SI}}{{break}}{{.}}{{end}}`},
-       {"range []int with break in else", "{{range .SI}}{{range .SI}}{{.}}{{else}}{{break}}{{end}}{{end}}", noError,
-               `{{range .SI}}{{range .SI}}{{.}}{{else}}{{break}}{{end}}{{end}}`},
-       {"range []int with continue", "{{range .SI}}{{continue}}{{.}}{{end}}", noError,
-               `{{range .SI}}{{continue}}{{.}}{{end}}`},
        {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
                `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
        {"template", "{{template `x`}}", noError,
@@ -294,12 +288,6 @@ var parseTests = []parseTest{
        {"empty pipeline", `{{printf "%d" ( ) }}`, hasError, ""},
        // Missing pipeline in block
        {"block definition", `{{block "foo"}}hello{{end}}`, hasError, ""},
-       // Invalid range control
-       {"break outside of range", `{{break}}`, hasError, ""},
-       {"break in range else, outside of range", `{{range .}}{{.}}{{else}}{{break}}{{end}}`, hasError, ""},
-       {"continue outside of range", `{{continue}}`, hasError, ""},
-       {"continue in range else, outside of range", `{{range .}}{{.}}{{else}}{{continue}}{{end}}`, hasError, ""},
-       {"additional break data", `{{range .}}{{break label}}{{end}}`, hasError, ""},
 }
 
 var builtins = map[string]interface{}{
index 61bbcd2957747188bee25b559cd71ed22416abab..2c232cf58a788cc7956298530f35fc928e64e73e 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 /*
-#cgo LDFLAGS: -c
+#cgo LDFLAGS: -L/nonexist
 
 void test() {
        xxx;            // ERROR HERE
diff --git a/libgo/misc/cgo/test/issue19832.go b/libgo/misc/cgo/test/issue19832.go
deleted file mode 100644 (file)
index 4458777..0000000
+++ /dev/null
@@ -1,16 +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.
-
-// Issue 19832. Functions taking a pointer typedef were being expanded and triggering a compiler error.
-
-package cgotest
-
-// typedef struct { int i; } *PS;
-// void T19832(PS p) {}
-import "C"
-import "testing"
-
-func test19832(t *testing.T) {
-       C.T19832(nil)
-}
index eab36834501ff78389eb00ad127a074c1f65b09e..7205c5a5a2505250adf5bfa54909f37bb27b8798 100644 (file)
@@ -4,6 +4,25 @@
 
 // +build !windows
 
+#include <stdint.h>
+#include <dlfcn.h>
+
+// Write our own versions of dlopen/dlsym/dlclose so that we represent
+// the opaque handle as a Go uintptr rather than a Go pointer to avoid
+// garbage collector confusion.  See issue 23663.
+
+uintptr_t dlopen4029(char* name, int flags) {
+       return (uintptr_t)(dlopen(name, flags));
+}
+
+uintptr_t dlsym4029(uintptr_t handle, char* name) {
+       return (uintptr_t)(dlsym((void*)(handle), name));
+}
+
+int dlclose4029(uintptr_t handle) {
+       return dlclose((void*)(handle));
+}
+
 void call4029(void *arg) {
        void (*fn)(void) = arg;
        fn();
index 5789b99ef67034f4644bac0aa9186e40675a1cf4..8e468d367d1ec9d9ad21ae6b564e64293bc93057 100644 (file)
@@ -7,10 +7,15 @@
 package cgotest
 
 /*
+#include <stdint.h>
 #include <dlfcn.h>
 #cgo linux LDFLAGS: -ldl
 
-extern void call4029(void *arg);
+extern uintptr_t dlopen4029(char*, int);
+extern uintptr_t dlsym4029(uintptr_t, char*);
+extern int dlclose4029(uintptr_t);
+
+extern void call4029(uintptr_t arg);
 */
 import "C"
 
@@ -51,15 +56,15 @@ func test4029(t *testing.T) {
 }
 
 func loadThySelf(t *testing.T, symbol string) {
-       this_process := C.dlopen(nil, C.RTLD_NOW)
-       if this_process == nil {
+       this_process := C.dlopen4029(nil, C.RTLD_NOW)
+       if this_process == 0 {
                t.Error("dlopen:", C.GoString(C.dlerror()))
                return
        }
-       defer C.dlclose(this_process)
+       defer C.dlclose4029(this_process)
 
-       symbol_address := C.dlsym(this_process, C.CString(symbol))
-       if symbol_address == nil {
+       symbol_address := C.dlsym4029(this_process, C.CString(symbol))
+       if symbol_address == 0 {
                t.Error("dlsym:", C.GoString(C.dlerror()))
                return
        }