[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 (*Paletted) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*RGBA) RGBA64At(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 (*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 (*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, Bounds, ColorModel, RGBA64At }
pkg image, type RGBA64Image interface, At(int, int) color.Color pkg image, type RGBA64Image interface, At(int, int) color.Color
pkg image, type RGBA64Image interface, Bounds() Rectangle pkg image, type RGBA64Image interface, Bounds() Rectangle

View file

@ -401,7 +401,7 @@ func Foo() bool {
<p><!-- golang.org/issue/40724 --> <p><!-- golang.org/issue/40724 -->
Go 1.17 implements a new way of passing function arguments and results using 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>, Windows on the 64-bit x86 architecture (the <code>linux/amd64</code>,
<code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a <code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a
representative set of Go packages and programs, benchmarking has shown representative set of Go packages and programs, benchmarking has shown
@ -811,8 +811,8 @@ func Foo() bool {
<p><!-- CL 311129 --> <p><!-- CL 311129 -->
The concrete image types (<code>RGBA</code>, <code>Gray16</code> and so on) 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> now implement a new <a href="/pkg/image/#RGBA64Image"><code>RGBA64Image</code></a>
interface. Those concrete types, other than the chroma-subsampling interface. The concrete types that previously implemented
related <code>YCbCr</code> and <code>NYCbCrA</code>, also now implement <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 <a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>, a
new interface in the <code>image/draw</code> package. new interface in the <code>image/draw</code> package.
</p> </p>
@ -993,7 +993,7 @@ func Foo() bool {
is no longer sufficient to guarantee that a call to is no longer sufficient to guarantee that a call to
<a href="/pkg/reflect/#Value.Convert"><code>Value.Convert</code></a> will not panic. <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. 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> </p>
</dd> </dd>
</dl><!-- reflect --> </dl><!-- reflect -->

View file

@ -1,6 +1,6 @@
<!--{ <!--{
"Title": "The Go Programming Language Specification", "Title": "The Go Programming Language Specification",
"Subtitle": "Version of Jun 22, 2021", "Subtitle": "Version of Jun 28, 2021",
"Path": "/ref/spec" "Path": "/ref/spec"
}--> }-->
@ -6789,11 +6789,17 @@ and whose length and capacity are <code>len</code>:
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:] (*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
</pre> </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> <p>
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>. 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>; 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 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. a <a href="#Run_time_panics">run-time panic</a> occurs.
</p> </p>

View file

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

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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): // TODO(rsc):
// Emit correct line number annotations. // Emit correct line number annotations.

View file

@ -138,6 +138,7 @@ var runtimeDecls = [...]struct {
{"growslice", funcTag, 116}, {"growslice", funcTag, 116},
{"unsafeslice", funcTag, 117}, {"unsafeslice", funcTag, 117},
{"unsafeslice64", funcTag, 118}, {"unsafeslice64", funcTag, 118},
{"unsafeslicecheckptr", funcTag, 118},
{"memmove", funcTag, 119}, {"memmove", funcTag, 119},
{"memclrNoHeapPointers", funcTag, 120}, {"memclrNoHeapPointers", funcTag, 120},
{"memclrHasPointers", 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[114] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
typs[115] = types.NewSlice(typs[2]) typs[115] = types.NewSlice(typs[2])
typs[116] = newSig(params(typs[1], typs[115], typs[15]), params(typs[115])) typs[116] = newSig(params(typs[1], typs[115], typs[15]), params(typs[115]))
typs[117] = newSig(params(typs[1], typs[15]), nil) typs[117] = newSig(params(typs[1], typs[7], typs[15]), nil)
typs[118] = newSig(params(typs[1], typs[22]), nil) typs[118] = newSig(params(typs[1], typs[7], typs[22]), nil)
typs[119] = newSig(params(typs[3], typs[3], typs[5]), nil) typs[119] = newSig(params(typs[3], typs[3], typs[5]), nil)
typs[120] = newSig(params(typs[7], 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])) 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 makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
func makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) 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 growslice(typ *byte, old []any, cap int) (ary []any)
func unsafeslice(typ *byte, len int) func unsafeslice(typ *byte, ptr unsafe.Pointer, len int)
func unsafeslice64(typ *byte, len int64) 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 memmove(to *any, frm *any, length uintptr)
func memclrNoHeapPointers(ptr unsafe.Pointer, n 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() t := n.X.Type()
if !t.IsPtr() { if !t.IsPtr() {
base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t) 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) { if !checkunsafeslice(&n.Y) {
n.SetType(nil) n.SetType(nil)
return n return n

View file

@ -1471,15 +1471,22 @@ toomany:
} }
func errorDetails(nl ir.Nodes, tstruct *types.Type, isddd bool) string { 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 // Suppress any return message signatures if:
// message signatures. See Issue https://golang.org/issues/19012. //
// (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 { 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 { for _, n := range nl {
if n.Type() == nil { if n.Type() == nil {
return "" return "" // case 2
} }
} }
return fmt.Sprintf("\n\thave %s\n\twant %v", fmtSignature(nl, isddd), tstruct) 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 { func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
ptr := safeExpr(n.X, init)
len := safeExpr(n.Y, init) len := safeExpr(n.Y, init)
fnname := "unsafeslice64" 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. // 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 // 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. // 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" fnname = "unsafeslice"
argtype = types.Types[types.TINT] lenType = types.Types[types.TINT]
} }
t := n.Type() t := n.Type()
// Call runtime.unsafeslice[64] to check that the length argument is // Call runtime.unsafeslice{,64,checkptr} to check ptr and len.
// non-negative and smaller than the max length allowed for the
// element type.
fn := typecheck.LookupRuntime(fnname) fn := typecheck.LookupRuntime(fnname)
init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(len, argtype))) init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), typecheck.Conv(len, lenType)))
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.
h := ir.NewSliceHeaderExpr(n.Pos(), t, h := ir.NewSliceHeaderExpr(n.Pos(), t,
typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]),

View file

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

View file

@ -1903,6 +1903,12 @@
// GCCGOTOOLDIR // GCCGOTOOLDIR
// If set, where to find gccgo tools, such as cgo. // If set, where to find gccgo tools, such as cgo.
// The default is based on how gccgo was configured. // 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 // GOROOT_FINAL
// The root of the installed Go tree, when it is // The root of the installed Go tree, when it is
// installed in a location other than where it is built. // 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 // The experiments flags are based on GOARCH, so they may
// need to change. TODO: This should be cleaned up. // 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 ctxt.ToolTags = nil
for _, exp := range buildcfg.EnabledExperiments() { for _, exp := range buildcfg.EnabledExperiments() {
ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp) ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)

View file

@ -10,6 +10,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"go/build" "go/build"
"internal/buildcfg"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
@ -72,6 +73,7 @@ func MkEnv() []cfg.EnvVar {
{Name: "GOCACHE", Value: cache.DefaultDir()}, {Name: "GOCACHE", Value: cache.DefaultDir()},
{Name: "GOENV", Value: envFile}, {Name: "GOENV", Value: envFile},
{Name: "GOEXE", Value: cfg.ExeSuffix}, {Name: "GOEXE", Value: cfg.ExeSuffix},
{Name: "GOEXPERIMENT", Value: buildcfg.GOEXPERIMENT()},
{Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")}, {Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")},
{Name: "GOHOSTARCH", Value: runtime.GOARCH}, {Name: "GOHOSTARCH", Value: runtime.GOARCH},
{Name: "GOHOSTOS", Value: runtime.GOOS}, {Name: "GOHOSTOS", Value: runtime.GOOS},
@ -197,6 +199,21 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
if *envU && *envW { if *envU && *envW {
base.Fatalf("go env: cannot use -u with -w") 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 := cfg.CmdEnv
env = append(env, ExtraEnvVars()...) 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? // Do we need to call ExtraEnvVarsCostly, which is a bit expensive?
needCostly := false needCostly := false
if *envU || *envW { if len(args) == 0 {
// 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 {
// We're listing all environment variables ("go env"), // We're listing all environment variables ("go env"),
// including the expensive ones. // including the expensive ones.
needCostly = true needCostly = true
@ -238,95 +248,6 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
env = append(env, ExtraEnvVarsCostly()...) 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 len(args) > 0 {
if *envJson { if *envJson {
var es []cfg.EnvVar var es []cfg.EnvVar
@ -351,6 +272,109 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
PrintEnv(os.Stdout, env) 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. // PrintEnv prints the environment variables to w.
func PrintEnv(w io.Writer, env []cfg.EnvVar) { func PrintEnv(w io.Writer, env []cfg.EnvVar) {
for _, e := range env { for _, e := range env {

View file

@ -610,6 +610,12 @@ Special-purpose environment variables:
GCCGOTOOLDIR GCCGOTOOLDIR
If set, where to find gccgo tools, such as cgo. If set, where to find gccgo tools, such as cgo.
The default is based on how gccgo was configured. 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 GOROOT_FINAL
The root of the installed Go tree, when it is The root of the installed Go tree, when it is
installed in a location other than where it is built. installed in a location other than where it is built.

View file

@ -145,24 +145,6 @@ func main() {
os.Exit(2) 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: BigCmdLoop:
for bigCmd := base.Go; ; { for bigCmd := base.Go; ; {
for _, cmd := range bigCmd.Commands { for _, cmd := range bigCmd.Commands {
@ -188,18 +170,7 @@ BigCmdLoop:
if !cmd.Runnable() { if !cmd.Runnable() {
continue continue
} }
cmd.Flag.Usage = func() { cmd.Usage() } invoke(cmd, args)
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()
base.Exit() base.Exit()
return 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() { func init() {
base.Usage = mainUsage 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"' stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"'
! go env -w GOMODCACHE=./test ! go env -w GOMODCACHE=./test
stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./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) { if p.To.Reg == REG_RSP && isADDSop(p.As) {
c.ctxt.Diag("illegal destination register: %v\n", p) c.ctxt.Diag("illegal destination register: %v\n", p)
} }
lsl0 := LSL0_64
if isADDWop(p.As) || isANDWop(p.As) { if isADDWop(p.As) || isANDWop(p.As) {
o1 = c.omovconst(AMOVW, p, &p.From, REGTMP) o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
lsl0 = LSL0_32
} else { } else {
o1 = c.omovconst(AMOVD, p, &p.From, REGTMP) 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 { if p.To.Reg == REGSP || r == REGSP {
o2 = c.opxrrr(p, p.As, false) o2 = c.opxrrr(p, p.As, false)
o2 |= REGTMP & 31 << 16 o2 |= REGTMP & 31 << 16
o2 |= LSL0_64 o2 |= uint32(lsl0)
} else { } else {
o2 = c.oprrr(p, p.As) o2 = c.oprrr(p, p.As)
o2 |= REGTMP & 31 << 16 /* shift is 0 */ 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") t.Skip("skipping windows amd64/386 only test")
} }
testenv.MustHaveCGO(t)
t.Run("aslr", func(t *testing.T) { t.Run("aslr", func(t *testing.T) {
testWindowsBuildmodeCSharedASLR(t, true) testWindowsBuildmodeCSharedASLR(t, true)
}) })

View file

@ -734,10 +734,12 @@ func processExtensions(out *Certificate) error {
if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) { if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
return errors.New("x509: invalid authority key identifier") return errors.New("x509: invalid authority key identifier")
} }
if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) { if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) {
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")
}
out.AuthorityKeyId = akid
} }
out.AuthorityKeyId = akid
case 37: case 37:
out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value) out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
if err != nil { 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" . "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 // Use the same importer for all std lib tests to
// avoid repeated importing of the same packages. // avoid repeated importing of the same packages.
var stdLibImporter = importer.Default() var stdLibImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)
func TestStdlib(t *testing.T) { func TestStdlib(t *testing.T) {
testenv.MustHaveGoBuild(t) testenv.MustHaveGoBuild(t)

View file

@ -6,7 +6,7 @@ package go1_17 // don't permit non-interface elements in interfaces
import ( import (
"fmt" "fmt"
syn "cmd/compile/internal/syntax" syn "regexp/syntax"
t1 "text/template" t1 "text/template"
t2 "html/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) 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 // 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) // The error message below should refer to the actual package name (syntax)
// not the local package name (syn). // 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 { type T struct {
@ -357,7 +357,7 @@ func issue35895() {
var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T 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. // 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), // Because both t1 and t2 have the same global package name (template),
// qualify packages with full path name in this case. // 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 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. // Bounds implements the Image interface.
func (r Rectangle) Bounds() Rectangle { func (r Rectangle) Bounds() Rectangle {
return r return r

View file

@ -116,7 +116,7 @@ type decoder struct {
// consumed when checking that the blockReader is exhausted. // consumed when checking that the blockReader is exhausted.
// //
// To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader // 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 { type blockReader struct {
d *decoder d *decoder
i, j uint8 // d.tmp[i:j] contains the buffered bytes 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), NewPaletted(r, palette.Plan9),
NewRGBA(r), NewRGBA(r),
NewRGBA64(r), NewRGBA64(r),
NewUniform(color.RGBA64{}),
NewYCbCr(r, YCbCrSubsampleRatio444), NewYCbCr(r, YCbCrSubsampleRatio444),
r,
} }
for _, tc := range testCases { for _, tc := range testCases {
switch tc := tc.(type) { switch tc := tc.(type) {
@ -226,6 +228,9 @@ func TestRGBA64Image(t *testing.T) {
// means that setting one pixel can modify neighboring pixels. They // means that setting one pixel can modify neighboring pixels. They
// don't have Set or SetRGBA64 methods because that side effect could // don't have Set or SetRGBA64 methods because that side effect could
// be surprising. Here, we just memset the channel buffers instead. // 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 { case interface {
SetRGBA64(x, y int, c color.RGBA64) SetRGBA64(x, y int, c color.RGBA64)
}: }:
@ -237,11 +242,18 @@ func TestRGBA64Image(t *testing.T) {
memset(tc.YCbCr.Cr, 0x99) memset(tc.YCbCr.Cr, 0x99)
memset(tc.A, 0xAA) memset(tc.A, 0xAA)
case *Uniform:
tc.C = color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF}
case *YCbCr: case *YCbCr:
memset(tc.Y, 0x77) memset(tc.Y, 0x77)
memset(tc.Cb, 0x88) memset(tc.Cb, 0x88)
memset(tc.Cr, 0x99) memset(tc.Cr, 0x99)
case Rectangle:
// No-op. Rectangle pixels' colors are immutable. They're always
// color.Opaque.
default: default:
t.Errorf("could not initialize pixels for %T", tc) t.Errorf("could not initialize pixels for %T", tc)
continue 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) 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. // Opaque scans the entire image and reports whether it is fully opaque.
func (c *Uniform) Opaque() bool { func (c *Uniform) Opaque() bool {
_, _, _, a := c.C.RGBA() _, _, _, a := c.C.RGBA()

View file

@ -6,7 +6,6 @@ package buildcfg
import ( import (
"fmt" "fmt"
"os"
"reflect" "reflect"
"strings" "strings"
@ -18,19 +17,19 @@ import (
// //
// (This is not necessarily the set of experiments the compiler itself // (This is not necessarily the set of experiments the compiler itself
// was built with.) // 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 // experimentBaseline specifies the experiment flags that are enabled by
// default in the current toolchain. This is, in effect, the "control" // default in the current toolchain. This is, in effect, the "control"
// configuration and any variation from this is an experiment. // configuration and any variation from this is an experiment.
var experimentBaseline = goexperiment.Flags{ var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
RegabiWrappers: regabiSupported, flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
RegabiReflect: regabiSupported, if err != nil {
RegabiArgs: regabiSupported, Error = err
} }
return flags, baseline
}()
const DefaultGOEXPERIMENT = defaultGOEXPERIMENT
// FramePointerEnabled enables the use of platform conventions for // FramePointerEnabled enables the use of platform conventions for
// saving frame pointers. // saving frame pointers.
@ -41,16 +40,27 @@ var experimentBaseline = goexperiment.Flags{
// Note: must agree with runtime.framepointer_enabled. // Note: must agree with runtime.framepointer_enabled.
var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64" 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. // Start with the statically enabled set of experiments.
flags := experimentBaseline flags = baseline
// Pick up any changes to the baseline configuration from the // Pick up any changes to the baseline configuration from the
// GOEXPERIMENT environment. This can be set at make.bash time // GOEXPERIMENT environment. This can be set at make.bash time
// and overridden at build time. // and overridden at build time.
env := envOr("GOEXPERIMENT", defaultGOEXPERIMENT) if goexp != "" {
if env != "" {
// Create a map of known experiment names. // Create a map of known experiment names.
names := make(map[string]func(bool)) names := make(map[string]func(bool))
rv := reflect.ValueOf(&flags).Elem() rv := reflect.ValueOf(&flags).Elem()
@ -71,7 +81,7 @@ func parseExperiments(goarch string) goexperiment.Flags {
} }
// Parse names. // Parse names.
for _, f := range strings.Split(env, ",") { for _, f := range strings.Split(goexp, ",") {
if f == "" { if f == "" {
continue continue
} }
@ -88,8 +98,8 @@ func parseExperiments(goarch string) goexperiment.Flags {
} }
set, ok := names[f] set, ok := names[f]
if !ok { if !ok {
fmt.Printf("unknown experiment %s\n", f) err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
os.Exit(2) return
} }
set(val) set(val)
} }
@ -107,9 +117,9 @@ func parseExperiments(goarch string) goexperiment.Flags {
} }
// Check regabi dependencies. // Check regabi dependencies.
if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) { 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 // 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. // UpdateExperiments updates the Experiment global based on a new GOARCH value.
// This is only required for cmd/go, which can change GOARCH after // This is only required for cmd/go, which can change GOARCH after
// program startup due to use of "go env -w". // program startup due to use of "go env -w".
func UpdateExperiments(goarch string) { func UpdateExperiments(goos, goarch, goexperiment string) {
Experiment = parseExperiments(goarch) 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) 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. // For documentation see comments of SetString.
func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) { func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) {
if _, _, err := z.scan(r, base); err != nil { 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) t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
} }
_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org") _, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected { 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) t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
} }
_, _, err = LookupSRV("hdr", "tcp", "golang.org") _, _, err = LookupSRV("hdr", "tcp", "golang.org.")
if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected { 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) t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
} }

View file

@ -5,6 +5,7 @@
package os_test package os_test
import ( import (
"errors"
"fmt" "fmt"
"io/fs" "io/fs"
"log" "log"
@ -71,9 +72,9 @@ func ExampleFileMode() {
} }
} }
func ExampleIsNotExist() { func ExampleErrNotExist() {
filename := "a-nonexistent-file" 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") fmt.Println("file does not exist")
} }
// Output: // Output:

View file

@ -1469,11 +1469,16 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
// Try different numbers of "..". // Try different numbers of "..".
for _, i := range []int{c, c + 1, c + 2} { 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)) 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) 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) t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
} else { default:
t.Logf("EvalSymlinks(%q) = %q", check, resolved) 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 return as.retval
} }
var ncgocall uint64 // number of cgo calls in total for dead m
// Call from Go to C. // Call from Go to C.
// //
// This must be nosplit because it's used for syscalls on some // 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. // 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") 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) { func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
if 0 < uintptr(p) && uintptr(p) < minLegalPointer { if 0 < uintptr(p) && uintptr(p) < minLegalPointer {
throw("checkptr: pointer arithmetic computed bad pointer value") 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"}, {"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
{"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"}, {"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"},
{"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\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 { 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. // NumCgoCall returns the number of cgo calls made by the current process.
func NumCgoCall() int64 { 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 { for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
n += int64(mp.ncgocall) n += int64(mp.ncgocall)
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1510,6 +1510,8 @@ found:
} }
unlock(&sched.lock) unlock(&sched.lock)
atomic.Xadd64(&ncgocall, int64(m.ncgocall))
// Release the P. // Release the P.
handoffp(releasep()) handoffp(releasep())
// After this point we must not have write barriers. // 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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !android && !js && !ppc64le //go:build race
// +build !android,!js,!ppc64le // +build race
// 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.
package race package race

View file

@ -114,19 +114,37 @@ func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
return makeslice(et, len, cap) 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)) mem, overflow := math.MulUintptr(et.size, uintptr(len))
if overflow || mem > maxAlloc || len < 0 { if overflow || mem > maxAlloc || len < 0 {
panicunsafeslicelen() panicunsafeslicelen()
} }
} }
func unsafeslice64(et *_type, len64 int64) { func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
len := int(len64) len := int(len64)
if int64(len) != len64 { if int64(len) != len64 {
panicunsafeslicelen() 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() { func panicunsafeslicelen() {

View file

@ -13,6 +13,8 @@ func init() {
register("CheckPtrArithmetic2", CheckPtrArithmetic2) register("CheckPtrArithmetic2", CheckPtrArithmetic2)
register("CheckPtrSize", CheckPtrSize) register("CheckPtrSize", CheckPtrSize)
register("CheckPtrSmall", CheckPtrSmall) register("CheckPtrSmall", CheckPtrSmall)
register("CheckPtrSliceOK", CheckPtrSliceOK)
register("CheckPtrSliceFail", CheckPtrSliceFail)
} }
func CheckPtrAlignmentNoPtr() { func CheckPtrAlignmentNoPtr() {
@ -49,3 +51,14 @@ func CheckPtrSize() {
func CheckPtrSmall() { func CheckPtrSmall() {
sink2 = unsafe.Pointer(uintptr(1)) 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))[:] // (*[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. // 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; // 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 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 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(len(s) == len(p))
assert(cap(s) == len(p)) assert(cap(s) == len(p))
// nil pointer // nil pointer with zero length returns nil
mustPanic(func() { _ = unsafe.Slice((*int)(nil), 0) }) assert(unsafe.Slice((*int)(nil), 0) == nil)
// nil pointer with positive length panics
mustPanic(func() { _ = unsafe.Slice((*int)(nil), 1) })
// negative length // negative length
var neg int = -1 var neg int = -1