[dev.typeparams] all: merge master (4711bf3) into dev.typeparams

Conflicts:

- src/cmd/compile/internal/walk/builtin.go

  On dev.typeparams, CL 330194 changed OCHECKNIL to not require manual
  SetTypecheck(1) anymore; while on master, CL 331070 got rid of the
  OCHECKNIL altogether by moving the check into the runtime support
  functions.

- src/internal/buildcfg/exp.go

  On master, CL 331109 refactored the logic for parsing the
  GOEXPERIMENT string, so that it could be more easily reused by
  cmd/go; while on dev.typeparams, several CLs tweaked the regabi
  experiment defaults.

Merge List:

+ 2021-06-30 4711bf30e5 doc/go1.17: linkify "language changes" in the runtime section
+ 2021-06-30 ed56ea73e8 path/filepath: deflake TestEvalSymlinksAboveRoot on darwin
+ 2021-06-30 c080d0323b cmd/dist: pass -Wno-unknown-warning-option in swig_callback_lto
+ 2021-06-30 7d0e9e6e74 image/gif: fix typo in the comment (io.ReadByte -> io.ByteReader)
+ 2021-06-30 0fa3265fe1 os: change example to avoid deprecated function
+ 2021-06-30 d19a53338f image: add Uniform.RGBA64At and Rectangle.RGBA64At
+ 2021-06-30 c45e800e0c crypto/x509: don't fail on optional auth key id fields
+ 2021-06-29 f9d50953b9 net: fix failure of TestCVE202133195
+ 2021-06-29 e294b8a49e doc/go1.17: fix typo "MacOS" -> "macOS"
+ 2021-06-29 3463852b76 math/big: fix typo of comment (`BytesScanner` to `ByteScanner`)
+ 2021-06-29 fd4b587da3 cmd/compile: suppress details error for invalid variadic argument type
+ 2021-06-29 e2e05af6e1 cmd/internal/obj/arm64: fix an encoding error of CMPW instruction
+ 2021-06-28 4bb0847b08 cmd/compile,runtime: change unsafe.Slice((*T)(nil), 0) to return []T(nil)
+ 2021-06-28 1519271a93 spec: change unsafe.Slice((*T)(nil), 0) to return []T(nil)
+ 2021-06-28 5385e2386b runtime/internal/atomic: drop Cas64 pointer indirection in comments
+ 2021-06-28 956c81bfe6 cmd/go: add GOEXPERIMENT to `go env` output
+ 2021-06-28 a1d27269d6 cmd/go: prep for 'go env' refactoring
+ 2021-06-28 901510ed4e cmd/link/internal/ld: skip the windows ASLR test when CGO_ENABLED=0
+ 2021-06-28 361159c055 cmd/cgo: fix 'see gmp.go' to 'see doc.go'
+ 2021-06-27 c95464f0ea internal/buildcfg: refactor GOEXPERIMENT parsing code somewhat
+ 2021-06-25 ed01ceaf48 runtime/race: use race build tag on syso_test.go
+ 2021-06-25 d1916e5e84 go/types: in TestCheck/issues.src, import regexp/syntax instead of cmd/compile/internal/syntax
+ 2021-06-25 5160896c69 go/types: in TestStdlib, import from source instead of export data
+ 2021-06-25 d01bc571f7 runtime: make ncgocall a global counter

Change-Id: I1ce4a3b3ff7c824c67ad66dd27d9d5f1d25c0023
This commit is contained in:
Matthew Dempsky 2021-06-30 18:19:26 -07:00
commit ad7e5b219e
50 changed files with 508 additions and 228 deletions

View file

@ -47,7 +47,9 @@ pkg image, method (*Paletted) RGBA64At(int, int) color.RGBA64
pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64
pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*Uniform) RGBA64At(int, int) color.RGBA64
pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64
pkg image, method (Rectangle) RGBA64At(int, int) color.RGBA64
pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At }
pkg image, type RGBA64Image interface, At(int, int) color.Color
pkg image, type RGBA64Image interface, Bounds() Rectangle

View file

@ -401,7 +401,7 @@ func Foo() bool {
<p><!-- golang.org/issue/40724 -->
Go 1.17 implements a new way of passing function arguments and results using
registers instead of the stack. This work is enabled for Linux, MacOS, and
registers instead of the stack. This work is enabled for Linux, macOS, and
Windows on the 64-bit x86 architecture (the <code>linux/amd64</code>,
<code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a
representative set of Go packages and programs, benchmarking has shown
@ -811,8 +811,8 @@ func Foo() bool {
<p><!-- CL 311129 -->
The concrete image types (<code>RGBA</code>, <code>Gray16</code> and so on)
now implement a new <a href="/pkg/image/#RGBA64Image"><code>RGBA64Image</code></a>
interface. Those concrete types, other than the chroma-subsampling
related <code>YCbCr</code> and <code>NYCbCrA</code>, also now implement
interface. The concrete types that previously implemented
<a href="/pkg/image/draw/#Image"><code>draw.Image</code></a> now also implement
<a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>, a
new interface in the <code>image/draw</code> package.
</p>
@ -993,7 +993,7 @@ func Foo() bool {
is no longer sufficient to guarantee that a call to
<a href="/pkg/reflect/#Value.Convert"><code>Value.Convert</code></a> will not panic.
It may panic when converting `[]T` to `*[N]T` if the slice's length is less than N.
See the language changes section above.
See the <a href="#language">language changes</a> section above.
</p>
</dd>
</dl><!-- reflect -->

View file

@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of Jun 22, 2021",
"Subtitle": "Version of Jun 28, 2021",
"Path": "/ref/spec"
}-->
@ -6789,11 +6789,17 @@ and whose length and capacity are <code>len</code>:
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
</pre>
<p>
As a special case, if <code>ptr</code> is <code>nil</code> and <code>len</code> is zero,
<code>Slice</code> returns <code>nil</code>.
</p>
<p>
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
if it is an untyped constant it is given type <code>int</code>.
If <code>ptr</code> is <code>nil</code> or <code>len</code> is negative at run time,
At run time, if <code>len</code> is negative,
or if <code>ptr</code> is <code>nil</code> and <code>len</code> is not zero,
a <a href="#Run_time_panics">run-time panic</a> occurs.
</p>

View file

@ -89,7 +89,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
CMP R1<<33, R2
CMP R22.SXTX, RSP // ffe336eb
CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb
CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff633b6b
CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff433b6b
CCMN MI, ZR, R1, $4 // e44341ba
// MADD Rn,Rm,Ra,Rd
MADD R1, R2, R3, R4 // 6408019b
@ -377,6 +377,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2
MOVW $0x10001000, RSP // MOVW $268439552, RSP // ff830432
ADDW $0x10001000, R1 // ADDW $268439552, R1 // fb83043221001b0b
ADDW $0x22220000, RSP, R3 // ADDW $572653568, RSP, R3 // 5b44a452e3433b0b
// move a large constant to a Vd.
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Cgo; see gmp.go for an overview.
// Cgo; see doc.go for an overview.
// TODO(rsc):
// Emit correct line number annotations.

View file

@ -138,6 +138,7 @@ var runtimeDecls = [...]struct {
{"growslice", funcTag, 116},
{"unsafeslice", funcTag, 117},
{"unsafeslice64", funcTag, 118},
{"unsafeslicecheckptr", funcTag, 118},
{"memmove", funcTag, 119},
{"memclrNoHeapPointers", funcTag, 120},
{"memclrHasPointers", funcTag, 120},
@ -341,8 +342,8 @@ func runtimeTypes() []*types.Type {
typs[114] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
typs[115] = types.NewSlice(typs[2])
typs[116] = newSig(params(typs[1], typs[115], typs[15]), params(typs[115]))
typs[117] = newSig(params(typs[1], typs[15]), nil)
typs[118] = newSig(params(typs[1], typs[22]), nil)
typs[117] = newSig(params(typs[1], typs[7], typs[15]), nil)
typs[118] = newSig(params(typs[1], typs[7], typs[22]), nil)
typs[119] = newSig(params(typs[3], typs[3], typs[5]), nil)
typs[120] = newSig(params(typs[7], typs[5]), nil)
typs[121] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))

View file

@ -183,8 +183,9 @@ func makeslice(typ *byte, len int, cap int) unsafe.Pointer
func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
func makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
func growslice(typ *byte, old []any, cap int) (ary []any)
func unsafeslice(typ *byte, len int)
func unsafeslice64(typ *byte, len int64)
func unsafeslice(typ *byte, ptr unsafe.Pointer, len int)
func unsafeslice64(typ *byte, ptr unsafe.Pointer, len int64)
func unsafeslicecheckptr(typ *byte, ptr unsafe.Pointer, len int64)
func memmove(to *any, frm *any, length uintptr)
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)

View file

@ -961,7 +961,14 @@ func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
t := n.X.Type()
if !t.IsPtr() {
base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
} else if t.Elem().NotInHeap() {
// TODO(mdempsky): This can be relaxed, but should only affect the
// Go runtime itself. End users should only see //go:notinheap
// types due to incomplete C structs in cgo, and those types don't
// have a meaningful size anyway.
base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
}
if !checkunsafeslice(&n.Y) {
n.SetType(nil)
return n

View file

@ -1471,15 +1471,22 @@ toomany:
}
func errorDetails(nl ir.Nodes, tstruct *types.Type, isddd bool) string {
// If we don't know any type at a call site, let's suppress any return
// message signatures. See Issue https://golang.org/issues/19012.
// Suppress any return message signatures if:
//
// (1) We don't know any type at a call site (see #19012).
// (2) Any node has an unknown type.
// (3) Invalid type for variadic parameter (see #46957).
if tstruct == nil {
return ""
return "" // case 1
}
// If any node has an unknown type, suppress it as well
if isddd && !nl[len(nl)-1].Type().IsSlice() {
return "" // case 3
}
for _, n := range nl {
if n.Type() == nil {
return ""
return "" // case 2
}
}
return fmt.Sprintf("\n\thave %s\n\twant %v", fmtSignature(nl, isddd), tstruct)

View file

@ -647,35 +647,28 @@ func walkRecoverFP(nn *ir.CallExpr, init *ir.Nodes) ir.Node {
}
func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
ptr := safeExpr(n.X, init)
len := safeExpr(n.Y, init)
fnname := "unsafeslice64"
argtype := types.Types[types.TINT64]
lenType := types.Types[types.TINT64]
// Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
// The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
// will be handled by the negative range checks in unsafeslice during runtime.
if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() {
if ir.ShouldCheckPtr(ir.CurFunc, 1) {
fnname = "unsafeslicecheckptr"
// for simplicity, unsafeslicecheckptr always uses int64
} else if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() {
fnname = "unsafeslice"
argtype = types.Types[types.TINT]
lenType = types.Types[types.TINT]
}
t := n.Type()
// Call runtime.unsafeslice[64] to check that the length argument is
// non-negative and smaller than the max length allowed for the
// element type.
// Call runtime.unsafeslice{,64,checkptr} to check ptr and len.
fn := typecheck.LookupRuntime(fnname)
init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(len, argtype)))
ptr := walkExpr(n.X, init)
check := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, ptr)
init.Append(typecheck.Stmt(check))
// TODO(mdempsky): checkptr instrumentation. Maybe merge into length
// check above, along with nil check? Need to be careful about
// notinheap pointers though: can't pass them as unsafe.Pointer.
init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), typecheck.Conv(len, lenType)))
h := ir.NewSliceHeaderExpr(n.Pos(), t,
typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]),

View file

@ -737,9 +737,9 @@ func (t *tester) registerTests() {
fn: func(dt *distTest) error {
cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
cmd.Env = append(os.Environ(),
"CGO_CFLAGS=-flto -Wno-lto-type-mismatch",
"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch",
"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch",
"CGO_CFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
)
return nil
},

View file

@ -1903,6 +1903,12 @@
// GCCGOTOOLDIR
// If set, where to find gccgo tools, such as cgo.
// The default is based on how gccgo was configured.
// GOEXPERIMENT
// Comma-separated list of toolchain experiments to enable or disable.
// The list of available experiments may change arbitrarily over time.
// See src/internal/goexperiment/flags.go for currently valid values.
// Warning: This variable is provided for the development and testing
// of the Go toolchain itself. Use beyond that purpose is unsupported.
// GOROOT_FINAL
// The root of the installed Go tree, when it is
// installed in a location other than where it is built.

View file

@ -79,7 +79,7 @@ func defaultContext() build.Context {
// The experiments flags are based on GOARCH, so they may
// need to change. TODO: This should be cleaned up.
buildcfg.UpdateExperiments(ctxt.GOARCH)
buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT))
ctxt.ToolTags = nil
for _, exp := range buildcfg.EnabledExperiments() {
ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)

View file

@ -10,6 +10,7 @@ import (
"encoding/json"
"fmt"
"go/build"
"internal/buildcfg"
"io"
"os"
"path/filepath"
@ -72,6 +73,7 @@ func MkEnv() []cfg.EnvVar {
{Name: "GOCACHE", Value: cache.DefaultDir()},
{Name: "GOENV", Value: envFile},
{Name: "GOEXE", Value: cfg.ExeSuffix},
{Name: "GOEXPERIMENT", Value: buildcfg.GOEXPERIMENT()},
{Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")},
{Name: "GOHOSTARCH", Value: runtime.GOARCH},
{Name: "GOHOSTOS", Value: runtime.GOOS},
@ -197,6 +199,21 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
if *envU && *envW {
base.Fatalf("go env: cannot use -u with -w")
}
// Handle 'go env -w' and 'go env -u' before calling buildcfg.Check,
// so they can be used to recover from an invalid configuration.
if *envW {
runEnvW(args)
return
}
if *envU {
runEnvU(args)
return
}
buildcfg.Check()
env := cfg.CmdEnv
env = append(env, ExtraEnvVars()...)
@ -206,14 +223,7 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
// Do we need to call ExtraEnvVarsCostly, which is a bit expensive?
needCostly := false
if *envU || *envW {
// We're overwriting or removing default settings,
// so it doesn't really matter what the existing settings are.
//
// Moreover, we haven't validated the new settings yet, so it is
// important that we NOT perform any actions based on them,
// such as initializing the builder to compute other variables.
} else if len(args) == 0 {
if len(args) == 0 {
// We're listing all environment variables ("go env"),
// including the expensive ones.
needCostly = true
@ -238,95 +248,6 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
env = append(env, ExtraEnvVarsCostly()...)
}
if *envW {
// Process and sanity-check command line.
if len(args) == 0 {
base.Fatalf("go env -w: no KEY=VALUE arguments given")
}
osEnv := make(map[string]string)
for _, e := range cfg.OrigEnv {
if i := strings.Index(e, "="); i >= 0 {
osEnv[e[:i]] = e[i+1:]
}
}
add := make(map[string]string)
for _, arg := range args {
i := strings.Index(arg, "=")
if i < 0 {
base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
}
key, val := arg[:i], arg[i+1:]
if err := checkEnvWrite(key, val); err != nil {
base.Fatalf("go env -w: %v", err)
}
if _, ok := add[key]; ok {
base.Fatalf("go env -w: multiple values for key: %s", key)
}
add[key] = val
if osVal := osEnv[key]; osVal != "" && osVal != val {
fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
}
}
goos, okGOOS := add["GOOS"]
goarch, okGOARCH := add["GOARCH"]
if okGOOS || okGOARCH {
if !okGOOS {
goos = cfg.Goos
}
if !okGOARCH {
goarch = cfg.Goarch
}
if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
base.Fatalf("go env -w: %v", err)
}
}
gotmp, okGOTMP := add["GOTMPDIR"]
if okGOTMP {
if !filepath.IsAbs(gotmp) && gotmp != "" {
base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
}
}
updateEnvFile(add, nil)
return
}
if *envU {
// Process and sanity-check command line.
if len(args) == 0 {
base.Fatalf("go env -u: no arguments given")
}
del := make(map[string]bool)
for _, arg := range args {
if err := checkEnvWrite(arg, ""); err != nil {
base.Fatalf("go env -u: %v", err)
}
del[arg] = true
}
if del["GOOS"] || del["GOARCH"] {
goos, goarch := cfg.Goos, cfg.Goarch
if del["GOOS"] {
goos = getOrigEnv("GOOS")
if goos == "" {
goos = build.Default.GOOS
}
}
if del["GOARCH"] {
goarch = getOrigEnv("GOARCH")
if goarch == "" {
goarch = build.Default.GOARCH
}
}
if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
base.Fatalf("go env -u: %v", err)
}
}
updateEnvFile(nil, del)
return
}
if len(args) > 0 {
if *envJson {
var es []cfg.EnvVar
@ -351,6 +272,109 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
PrintEnv(os.Stdout, env)
}
func runEnvW(args []string) {
// Process and sanity-check command line.
if len(args) == 0 {
base.Fatalf("go env -w: no KEY=VALUE arguments given")
}
osEnv := make(map[string]string)
for _, e := range cfg.OrigEnv {
if i := strings.Index(e, "="); i >= 0 {
osEnv[e[:i]] = e[i+1:]
}
}
add := make(map[string]string)
for _, arg := range args {
i := strings.Index(arg, "=")
if i < 0 {
base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
}
key, val := arg[:i], arg[i+1:]
if err := checkEnvWrite(key, val); err != nil {
base.Fatalf("go env -w: %v", err)
}
if _, ok := add[key]; ok {
base.Fatalf("go env -w: multiple values for key: %s", key)
}
add[key] = val
if osVal := osEnv[key]; osVal != "" && osVal != val {
fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
}
}
if err := checkBuildConfig(add, nil); err != nil {
base.Fatalf("go env -w: %v", err)
}
gotmp, okGOTMP := add["GOTMPDIR"]
if okGOTMP {
if !filepath.IsAbs(gotmp) && gotmp != "" {
base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
}
}
updateEnvFile(add, nil)
}
func runEnvU(args []string) {
// Process and sanity-check command line.
if len(args) == 0 {
base.Fatalf("go env -u: no arguments given")
}
del := make(map[string]bool)
for _, arg := range args {
if err := checkEnvWrite(arg, ""); err != nil {
base.Fatalf("go env -u: %v", err)
}
del[arg] = true
}
if err := checkBuildConfig(nil, del); err != nil {
base.Fatalf("go env -u: %v", err)
}
updateEnvFile(nil, del)
}
// checkBuildConfig checks whether the build configuration is valid
// after the specified configuration environment changes are applied.
func checkBuildConfig(add map[string]string, del map[string]bool) error {
// get returns the value for key after applying add and del and
// reports whether it changed. cur should be the current value
// (i.e., before applying changes) and def should be the default
// value (i.e., when no environment variables are provided at all).
get := func(key, cur, def string) (string, bool) {
if val, ok := add[key]; ok {
return val, true
}
if del[key] {
val := getOrigEnv(key)
if val == "" {
val = def
}
return val, true
}
return cur, false
}
goos, okGOOS := get("GOOS", cfg.Goos, build.Default.GOOS)
goarch, okGOARCH := get("GOARCH", cfg.Goarch, build.Default.GOARCH)
if okGOOS || okGOARCH {
if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
return err
}
}
goexperiment, okGOEXPERIMENT := get("GOEXPERIMENT", buildcfg.GOEXPERIMENT(), "")
if okGOEXPERIMENT {
if _, _, err := buildcfg.ParseGOEXPERIMENT(goos, goarch, goexperiment); err != nil {
return err
}
}
return nil
}
// PrintEnv prints the environment variables to w.
func PrintEnv(w io.Writer, env []cfg.EnvVar) {
for _, e := range env {

View file

@ -610,6 +610,12 @@ Special-purpose environment variables:
GCCGOTOOLDIR
If set, where to find gccgo tools, such as cgo.
The default is based on how gccgo was configured.
GOEXPERIMENT
Comma-separated list of toolchain experiments to enable or disable.
The list of available experiments may change arbitrarily over time.
See src/internal/goexperiment/flags.go for currently valid values.
Warning: This variable is provided for the development and testing
of the Go toolchain itself. Use beyond that purpose is unsupported.
GOROOT_FINAL
The root of the installed Go tree, when it is
installed in a location other than where it is built.

View file

@ -145,24 +145,6 @@ func main() {
os.Exit(2)
}
if err := buildcfg.Error; err != nil {
fmt.Fprintf(os.Stderr, "go: %v\n", buildcfg.Error)
os.Exit(2)
}
// Set environment (GOOS, GOARCH, etc) explicitly.
// In theory all the commands we invoke should have
// the same default computation of these as we do,
// but in practice there might be skew
// This makes sure we all agree.
cfg.OrigEnv = os.Environ()
cfg.CmdEnv = envcmd.MkEnv()
for _, env := range cfg.CmdEnv {
if os.Getenv(env.Name) != env.Value {
os.Setenv(env.Name, env.Value)
}
}
BigCmdLoop:
for bigCmd := base.Go; ; {
for _, cmd := range bigCmd.Commands {
@ -188,18 +170,7 @@ BigCmdLoop:
if !cmd.Runnable() {
continue
}
cmd.Flag.Usage = func() { cmd.Usage() }
if cmd.CustomFlags {
args = args[1:]
} else {
base.SetFromGOFLAGS(&cmd.Flag)
cmd.Flag.Parse(args[1:])
args = cmd.Flag.Args()
}
ctx := maybeStartTrace(context.Background())
ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
cmd.Run(ctx, cmd, args)
span.Done()
invoke(cmd, args)
base.Exit()
return
}
@ -213,6 +184,39 @@ BigCmdLoop:
}
}
func invoke(cmd *base.Command, args []string) {
// 'go env' handles checking the build config
if cmd != envcmd.CmdEnv {
buildcfg.Check()
}
// Set environment (GOOS, GOARCH, etc) explicitly.
// In theory all the commands we invoke should have
// the same default computation of these as we do,
// but in practice there might be skew
// This makes sure we all agree.
cfg.OrigEnv = os.Environ()
cfg.CmdEnv = envcmd.MkEnv()
for _, env := range cfg.CmdEnv {
if os.Getenv(env.Name) != env.Value {
os.Setenv(env.Name, env.Value)
}
}
cmd.Flag.Usage = func() { cmd.Usage() }
if cmd.CustomFlags {
args = args[1:]
} else {
base.SetFromGOFLAGS(&cmd.Flag)
cmd.Flag.Parse(args[1:])
args = cmd.Flag.Args()
}
ctx := maybeStartTrace(context.Background())
ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
cmd.Run(ctx, cmd, args)
span.Done()
}
func init() {
base.Usage = mainUsage
}

17
src/cmd/go/testdata/script/env_exp.txt vendored Normal file
View file

@ -0,0 +1,17 @@
# Test GOEXPERIMENT variable
# go env shows default empty GOEXPERIMENT
go env
stdout GOEXPERIMENT=
# go env shows valid experiments
env GOEXPERIMENT=fieldtrack,staticlockranking
go env GOEXPERIMENT
stdout '.*fieldtrack.*staticlockranking.*'
go env
stdout 'GOEXPERIMENT=.*fieldtrack.*staticlockranking.*'
# go env rejects unknown experiments
env GOEXPERIMENT=bad
! go env GOEXPERIMENT
stderr 'unknown GOEXPERIMENT bad'

View file

@ -0,0 +1,30 @@
# Test that we can unset variables, even if initially invalid,
# as long as resulting config is valid.
env GOENV=badenv
env GOOS=
env GOARCH=
env GOEXPERIMENT=
! go env
stderr '^go(\.exe)?: unknown GOEXPERIMENT badexp$'
go env -u GOEXPERIMENT
! go env
stderr '^cmd/go: unsupported GOOS/GOARCH pair bados/badarch$'
! go env -u GOOS
stderr '^go env -u: unsupported GOOS/GOARCH pair \w+/badarch$'
! go env -u GOARCH
stderr '^go env -u: unsupported GOOS/GOARCH pair bados/\w+$'
go env -u GOOS GOARCH
go env
-- badenv --
GOOS=bados
GOARCH=badarch
GOEXPERIMENT=badexp

View file

@ -179,3 +179,9 @@ stderr 'unsupported GOOS/GOARCH.*windows/mips$'
stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"'
! go env -w GOMODCACHE=./test
stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./test"'
# go env -w checks validity of GOEXPERIMENT
env GOEXPERIMENT=
! go env -w GOEXPERIMENT=badexp
stderr 'unknown GOEXPERIMENT badexp'
go env -w GOEXPERIMENT=fieldtrack

View file

@ -4333,8 +4333,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
if p.To.Reg == REG_RSP && isADDSop(p.As) {
c.ctxt.Diag("illegal destination register: %v\n", p)
}
lsl0 := LSL0_64
if isADDWop(p.As) || isANDWop(p.As) {
o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
lsl0 = LSL0_32
} else {
o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
}
@ -4350,7 +4352,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
if p.To.Reg == REGSP || r == REGSP {
o2 = c.opxrrr(p, p.As, false)
o2 |= REGTMP & 31 << 16
o2 |= LSL0_64
o2 |= uint32(lsl0)
} else {
o2 = c.oprrr(p, p.As)
o2 |= REGTMP & 31 << 16 /* shift is 0 */

View file

@ -174,6 +174,8 @@ func TestWindowsBuildmodeCSharedASLR(t *testing.T) {
t.Skip("skipping windows amd64/386 only test")
}
testenv.MustHaveCGO(t)
t.Run("aslr", func(t *testing.T) {
testWindowsBuildmodeCSharedASLR(t, true)
})

View file

@ -734,10 +734,12 @@ func processExtensions(out *Certificate) error {
if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
return errors.New("x509: invalid authority key identifier")
}
if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) {
return errors.New("x509: invalid authority key identifier")
if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) {
if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) {
return errors.New("x509: invalid authority key identifier")
}
out.AuthorityKeyId = akid
}
out.AuthorityKeyId = akid
case 37:
out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
if err != nil {

View file

@ -3174,3 +3174,45 @@ func TestSigAlgMismatch(t *testing.T) {
}
}
}
const optionalAuthKeyIDPEM = `-----BEGIN CERTIFICATE-----
MIIFEjCCBHugAwIBAgICAQwwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MzkxNloX
DTI0MDYyOTE3MzkxNlowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVs
ZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAy
IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A
MIIBCAKCAQEAtzLI/ulxpgSFrQwRZN/OTe/IAxiHP6Gr+zymn/DDodrU2G4rU5D7
JKQ+hPCe6F/s5SdE9SimP3ve4CrwyK9TL57KBQGTHo9mHDmnTfpatnMEJWbrd3/n
WcZKmSUUVOsmx/N/GdUwcI+vsEYq/63rKe3Xn6oEh6PU+YmlNF/bQ5GCNtlmPLG4
uYL9nDo+EMg77wZlZnqbGRg9/3FRPDAuX749d3OyXQZswyNWmiuFJpIcpwKz5D8N
rwh5grg2Peqc0zWzvGnK9cyd6P1kjReAM25eSl2ZyR6HtJ0awNVuEzUjXt+bXz3v
1vd2wuo+u3gNHEJnawTY+Nbab4vyRKABqwIBA6OCAfMwggHvMB0GA1UdDgQWBBS/
X7fRzt0fhvRbVazc1xDCDqmI5zCB0gYDVR0jBIHKMIHHoYHBpIG+MIG7MSQwIgYD
VQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNVBAoTDlZhbGlD
ZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBvbGljeSBWYWxp
ZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52YWxpY2VydC5j
b20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbYIBATAPBgNVHRMB
Af8EBTADAQH/MDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29j
c3Auc3RhcmZpZWxkdGVjaC5jb20wSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2Nl
cnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3Jvb3QuY3Js
MFEGA1UdIARKMEgwRgYEVR0gADA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY2VydGlm
aWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkwDgYDVR0PAQH/BAQD
AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKVi8afCXSWlcD284ipxs33kDTcdVWptobCr
mADkhWBKIMuh8D1195TaQ39oXCUIuNJ9MxB73HZn8bjhU3zhxoNbKXuNSm8uf0So
GkVrMgfHeMpkksK0hAzc3S1fTbvdiuo43NlmouxBulVtWmQ9twPMHOKRUJ7jCUSV
FxdzPcwl
-----END CERTIFICATE-----`
func TestAuthKeyIdOptional(t *testing.T) {
b, _ := pem.Decode([]byte(optionalAuthKeyIDPEM))
if b == nil {
t.Fatalf("couldn't decode test certificate")
}
_, err := ParseCertificate(b.Bytes)
if err != nil {
t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err)
}
}

View file

@ -26,9 +26,15 @@ import (
. "go/types"
)
// The cmd/*/internal packages may have been deleted as part of a binary
// release. Import from source instead.
//
// (See https://golang.org/issue/43232 and
// https://github.com/golang/build/blob/df58bbac082bc87c4a3cdfe336d1ffe60bbaa916/cmd/release/release.go#L533-L545.)
//
// Use the same importer for all std lib tests to
// avoid repeated importing of the same packages.
var stdLibImporter = importer.Default()
var stdLibImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)
func TestStdlib(t *testing.T) {
testenv.MustHaveGoBuild(t)

View file

@ -6,7 +6,7 @@ package go1_17 // don't permit non-interface elements in interfaces
import (
"fmt"
syn "cmd/compile/internal/syntax"
syn "regexp/syntax"
t1 "text/template"
t2 "html/template"
)
@ -329,10 +329,10 @@ func (... /* ERROR can only use ... with final parameter */ TT) f()
func issue28281g() (... /* ERROR can only use ... with final parameter */ TT)
// Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
func issue26234a(f *syn.File) {
func issue26234a(f *syn.Prog) {
// The error message below should refer to the actual package name (syntax)
// not the local package name (syn).
f.foo /* ERROR f\.foo undefined \(type \*syntax\.File has no field or method foo\) */
f.foo /* ERROR f\.foo undefined \(type \*syntax\.Prog has no field or method foo\) */
}
type T struct {
@ -357,7 +357,7 @@ func issue35895() {
var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T
// There is only one package with name syntax imported, only use the (global) package name in error messages.
var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File
var _ *syn.Prog = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.Prog
// Because both t1 and t2 have the same global package name (template),
// qualify packages with full path name in this case.

View file

@ -246,6 +246,14 @@ func (r Rectangle) At(x, y int) color.Color {
return color.Transparent
}
// RGBA64At implements the RGBA64Image interface.
func (r Rectangle) RGBA64At(x, y int) color.RGBA64 {
if (Point{x, y}).In(r) {
return color.RGBA64{0xffff, 0xffff, 0xffff, 0xffff}
}
return color.RGBA64{}
}
// Bounds implements the Image interface.
func (r Rectangle) Bounds() Rectangle {
return r

View file

@ -116,7 +116,7 @@ type decoder struct {
// consumed when checking that the blockReader is exhausted.
//
// To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader
// implements io.ReadByte and buffers blocks into the decoder's "tmp" buffer.
// implements io.ByteReader and buffers blocks into the decoder's "tmp" buffer.
type blockReader struct {
d *decoder
i, j uint8 // d.tmp[i:j] contains the buffered bytes

View file

@ -213,7 +213,9 @@ func TestRGBA64Image(t *testing.T) {
NewPaletted(r, palette.Plan9),
NewRGBA(r),
NewRGBA64(r),
NewUniform(color.RGBA64{}),
NewYCbCr(r, YCbCrSubsampleRatio444),
r,
}
for _, tc := range testCases {
switch tc := tc.(type) {
@ -226,6 +228,9 @@ func TestRGBA64Image(t *testing.T) {
// means that setting one pixel can modify neighboring pixels. They
// don't have Set or SetRGBA64 methods because that side effect could
// be surprising. Here, we just memset the channel buffers instead.
//
// The Uniform and Rectangle types are also special-cased, as they
// don't have a Set or SetRGBA64 method.
case interface {
SetRGBA64(x, y int, c color.RGBA64)
}:
@ -237,11 +242,18 @@ func TestRGBA64Image(t *testing.T) {
memset(tc.YCbCr.Cr, 0x99)
memset(tc.A, 0xAA)
case *Uniform:
tc.C = color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF}
case *YCbCr:
memset(tc.Y, 0x77)
memset(tc.Cb, 0x88)
memset(tc.Cr, 0x99)
case Rectangle:
// No-op. Rectangle pixels' colors are immutable. They're always
// color.Opaque.
default:
t.Errorf("could not initialize pixels for %T", tc)
continue

View file

@ -41,6 +41,11 @@ func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point
func (c *Uniform) At(x, y int) color.Color { return c.C }
func (c *Uniform) RGBA64At(x, y int) color.RGBA64 {
r, g, b, a := c.C.RGBA()
return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
}
// Opaque scans the entire image and reports whether it is fully opaque.
func (c *Uniform) Opaque() bool {
_, _, _, a := c.C.RGBA()

View file

@ -6,7 +6,6 @@ package buildcfg
import (
"fmt"
"os"
"reflect"
"strings"
@ -18,19 +17,19 @@ import (
//
// (This is not necessarily the set of experiments the compiler itself
// was built with.)
var Experiment goexperiment.Flags = parseExperiments(GOARCH)
var regabiSupported = GOARCH == "amd64" || GOARCH == "arm64"
var regabiDeveloping = false
//
// experimentBaseline specifies the experiment flags that are enabled by
// default in the current toolchain. This is, in effect, the "control"
// configuration and any variation from this is an experiment.
var experimentBaseline = goexperiment.Flags{
RegabiWrappers: regabiSupported,
RegabiReflect: regabiSupported,
RegabiArgs: regabiSupported,
}
var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
if err != nil {
Error = err
}
return flags, baseline
}()
const DefaultGOEXPERIMENT = defaultGOEXPERIMENT
// FramePointerEnabled enables the use of platform conventions for
// saving frame pointers.
@ -41,16 +40,27 @@ var experimentBaseline = goexperiment.Flags{
// Note: must agree with runtime.framepointer_enabled.
var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
func parseExperiments(goarch string) goexperiment.Flags {
// ParseGOEXPERIMENT parses a (GOOS, GOARCH, GOEXPERIMENT)
// configuration tuple and returns the enabled and baseline experiment
// flag sets.
//
// TODO(mdempsky): Move to internal/goexperiment.
func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
regabiSupported := goarch == "amd64" || goarch == "arm64"
baseline = goexperiment.Flags{
RegabiWrappers: regabiSupported,
RegabiReflect: regabiSupported,
RegabiArgs: regabiSupported,
}
// Start with the statically enabled set of experiments.
flags := experimentBaseline
flags = baseline
// Pick up any changes to the baseline configuration from the
// GOEXPERIMENT environment. This can be set at make.bash time
// and overridden at build time.
env := envOr("GOEXPERIMENT", defaultGOEXPERIMENT)
if env != "" {
if goexp != "" {
// Create a map of known experiment names.
names := make(map[string]func(bool))
rv := reflect.ValueOf(&flags).Elem()
@ -71,7 +81,7 @@ func parseExperiments(goarch string) goexperiment.Flags {
}
// Parse names.
for _, f := range strings.Split(env, ",") {
for _, f := range strings.Split(goexp, ",") {
if f == "" {
continue
}
@ -88,8 +98,8 @@ func parseExperiments(goarch string) goexperiment.Flags {
}
set, ok := names[f]
if !ok {
fmt.Printf("unknown experiment %s\n", f)
os.Exit(2)
err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
return
}
set(val)
}
@ -107,9 +117,9 @@ func parseExperiments(goarch string) goexperiment.Flags {
}
// Check regabi dependencies.
if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) {
Error = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
}
return flags
return
}
// expList returns the list of lower-cased experiment names for
@ -165,6 +175,10 @@ func AllExperiments() []string {
// UpdateExperiments updates the Experiment global based on a new GOARCH value.
// This is only required for cmd/go, which can change GOARCH after
// program startup due to use of "go env -w".
func UpdateExperiments(goarch string) {
Experiment = parseExperiments(goarch)
func UpdateExperiments(goos, goarch, goexperiment string) {
var err error
Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
if err != nil {
Error = err
}
}

View file

@ -425,7 +425,7 @@ func (z *Int) SetString(s string, base int) (*Int, bool) {
return z.setFromScanner(strings.NewReader(s), base)
}
// setFromScanner implements SetString given an io.BytesScanner.
// setFromScanner implements SetString given an io.ByteScanner.
// For documentation see comments of SetString.
func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) {
if _, _, err := z.scan(r, base); err != nil {

View file

@ -1921,12 +1921,12 @@ func TestCVE202133195(t *testing.T) {
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
}
_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org")
if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
}
_, _, err = LookupSRV("hdr", "tcp", "golang.org")
if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
_, _, err = LookupSRV("hdr", "tcp", "golang.org.")
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
}

View file

@ -5,6 +5,7 @@
package os_test
import (
"errors"
"fmt"
"io/fs"
"log"
@ -71,9 +72,9 @@ func ExampleFileMode() {
}
}
func ExampleIsNotExist() {
func ExampleErrNotExist() {
filename := "a-nonexistent-file"
if _, err := os.Stat(filename); os.IsNotExist(err) {
if _, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) {
fmt.Println("file does not exist")
}
// Output:

View file

@ -1469,11 +1469,16 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
// Try different numbers of "..".
for _, i := range []int{c, c + 1, c + 2} {
check := strings.Join([]string{evalTmpDir, strings.Join(dd[:i], string(os.PathSeparator)), evalTmpDir[len(vol)+1:], "b", "file"}, string(os.PathSeparator))
if resolved, err := filepath.EvalSymlinks(check); err != nil {
resolved, err := filepath.EvalSymlinks(check)
switch {
case runtime.GOOS == "darwin" && errors.Is(err, fs.ErrNotExist):
// On darwin, the temp dir is sometimes cleaned up mid-test (issue 37910).
testenv.SkipFlaky(t, 37910)
case err != nil:
t.Errorf("EvalSymlinks(%q) failed: %v", check, err)
} else if !strings.HasSuffix(resolved, wantSuffix) {
case !strings.HasSuffix(resolved, wantSuffix):
t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
} else {
default:
t.Logf("EvalSymlinks(%q) = %q", check, resolved)
}
}

View file

@ -111,6 +111,8 @@ func syscall_cgocaller(fn unsafe.Pointer, args ...uintptr) uintptr {
return as.retval
}
var ncgocall uint64 // number of cgo calls in total for dead m
// Call from Go to C.
//
// This must be nosplit because it's used for syscalls on some

View file

@ -16,11 +16,30 @@ func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) {
}
// Check that (*[n]elem)(p) doesn't straddle multiple heap objects.
if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) {
// TODO(mdempsky): Fix #46938 so we don't need to worry about overflow here.
if checkptrStraddles(p, n*elem.size) {
throw("checkptr: converted pointer straddles multiple allocations")
}
}
// checkptrStraddles reports whether the first size-bytes of memory
// addressed by ptr is known to straddle more than one Go allocation.
func checkptrStraddles(ptr unsafe.Pointer, size uintptr) bool {
if size <= 1 {
return false
}
end := add(ptr, size-1)
if uintptr(end) < uintptr(ptr) {
return true
}
// TODO(mdempsky): Detect when [ptr, end] contains Go allocations,
// but neither ptr nor end point into one themselves.
return checkptrBase(ptr) != checkptrBase(end)
}
func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
if 0 < uintptr(p) && uintptr(p) < minLegalPointer {
throw("checkptr: pointer arithmetic computed bad pointer value")

View file

@ -30,6 +30,8 @@ func TestCheckPtr(t *testing.T) {
{"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
{"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"},
{"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"},
{"CheckPtrSliceOK", ""},
{"CheckPtrSliceFail", "fatal error: checkptr: unsafe.Slice result straddles multiple allocations\n"},
}
for _, tc := range testCases {

View file

@ -45,7 +45,7 @@ func NumCPU() int {
// NumCgoCall returns the number of cgo calls made by the current process.
func NumCgoCall() int64 {
var n int64
var n = int64(atomic.Load64(&ncgocall))
for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
n += int64(mp.ncgocall)
}

View file

@ -37,7 +37,7 @@ TEXT ·Cas(SB),NOSPLIT,$0-17
// bool ·Cas64(uint64 *val, uint64 old, uint64 new)
// Atomically:
// if(*val == *old){
// if(*val == old){
// *val = new;
// return 1;
// } else {

View file

@ -192,7 +192,7 @@ ok:
// bool ·Cas64(uint64 *ptr, uint64 old, uint64 new)
// Atomically:
// if(*val == *old){
// if(*val == old){
// *val = new;
// return 1;
// } else {

View file

@ -37,7 +37,7 @@ cas_fail:
// bool cas64(uint64 *ptr, uint64 old, uint64 new)
// Atomically:
// if(*val == *old){
// if(*val == old){
// *val = new;
// return 1;
// } else {

View file

@ -107,7 +107,7 @@ cas_fail:
// bool ·Cas64(uint64 *ptr, uint64 old, uint64 new)
// Atomically:
// if(*val == *old){
// if(*val == old){
// *val = new;
// return 1;
// } else {

View file

@ -30,8 +30,9 @@
#include "textflag.h"
// func Cas(ptr *uint64, old, new uint64) bool
// Atomically:
// if(*val == *old){
// if(*val == old){
// *val = new;
// return 1;
// } else {

View file

@ -1510,6 +1510,8 @@ found:
}
unlock(&sched.lock)
atomic.Xadd64(&ncgocall, int64(m.ncgocall))
// Release the P.
handoffp(releasep())
// After this point we must not have write barriers.

View file

@ -2,14 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !android && !js && !ppc64le
// +build !android,!js,!ppc64le
// Note: we don't run on Android or ppc64 because if there is any non-race test
// file in this package, the OS tries to link the .syso file into the
// test (even when we're not in race mode), which fails. I'm not sure
// why, but easiest to just punt - as long as a single builder runs
// this test, we're good.
//go:build race
// +build race
package race

View file

@ -114,19 +114,37 @@ func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
return makeslice(et, len, cap)
}
func unsafeslice(et *_type, len int) {
func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
if len == 0 {
return
}
if ptr == nil {
panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
}
mem, overflow := math.MulUintptr(et.size, uintptr(len))
if overflow || mem > maxAlloc || len < 0 {
panicunsafeslicelen()
}
}
func unsafeslice64(et *_type, len64 int64) {
func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
len := int(len64)
if int64(len) != len64 {
panicunsafeslicelen()
}
unsafeslice(et, len)
unsafeslice(et, ptr, len)
}
func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
unsafeslice64(et, ptr, len64)
// Check that underlying array doesn't straddle multiple heap objects.
// unsafeslice64 has already checked for overflow.
if checkptrStraddles(ptr, uintptr(len64)*et.size) {
throw("checkptr: unsafe.Slice result straddles multiple allocations")
}
}
func panicunsafeslicelen() {

View file

@ -13,6 +13,8 @@ func init() {
register("CheckPtrArithmetic2", CheckPtrArithmetic2)
register("CheckPtrSize", CheckPtrSize)
register("CheckPtrSmall", CheckPtrSmall)
register("CheckPtrSliceOK", CheckPtrSliceOK)
register("CheckPtrSliceFail", CheckPtrSliceFail)
}
func CheckPtrAlignmentNoPtr() {
@ -49,3 +51,14 @@ func CheckPtrSize() {
func CheckPtrSmall() {
sink2 = unsafe.Pointer(uintptr(1))
}
func CheckPtrSliceOK() {
p := new([4]int64)
sink2 = unsafe.Slice(&p[1], 3)
}
func CheckPtrSliceFail() {
p := new(int64)
sink2 = p
sink2 = unsafe.Slice(p, 100)
}

View file

@ -221,8 +221,11 @@ func Add(ptr Pointer, len IntegerType) Pointer
//
// (*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
//
// As a special case, if ptr is nil and len is zero, Slice returns nil.
//
// The len argument must be of integer type or an untyped constant.
// A constant len argument must be non-negative and representable by a value of type int;
// if it is an untyped constant it is given type int.
// If ptr is nil or len is negative at run time, a run-time panic occurs.
// At run time, if len is negative, or if ptr is nil and len is not zero,
// a run-time panic occurs.
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType

View file

@ -0,0 +1,13 @@
// errorcheck
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func f(a int, b ...int) {}
func main() {
f(nil...) // ERROR "not enough arguments in call to f$"
}

View file

@ -30,8 +30,11 @@ func main() {
assert(len(s) == len(p))
assert(cap(s) == len(p))
// nil pointer
mustPanic(func() { _ = unsafe.Slice((*int)(nil), 0) })
// nil pointer with zero length returns nil
assert(unsafe.Slice((*int)(nil), 0) == nil)
// nil pointer with positive length panics
mustPanic(func() { _ = unsafe.Slice((*int)(nil), 1) })
// negative length
var neg int = -1