Update to go1.24.5

This commit is contained in:
Vorapol Rinsatitnon
2025-07-10 22:34:08 +07:00
parent b065c9156b
commit 5f4d34edc5
40 changed files with 456 additions and 130 deletions

View File

@@ -42,6 +42,8 @@ func TestASAN(t *testing.T) {
{src: "asan_global3_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global3_fail.go:13"},
{src: "asan_global4_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global4_fail.go:21"},
{src: "asan_global5.go"},
{src: "asan_global_asm"},
{src: "asan_global_asm2_fail", memoryAccessError: "global-buffer-overflow", errorLocation: "main.go:17"},
{src: "arena_fail.go", memoryAccessError: "use-after-poison", errorLocation: "arena_fail.go:26", experiments: []string{"arenas"}},
}
for _, tc := range cases {

View File

@@ -536,7 +536,7 @@ func (c *config) checkRuntime() (skip bool, err error) {
// srcPath returns the path to the given file relative to this test's source tree.
func srcPath(path string) string {
return filepath.Join("testdata", path)
return "./testdata/" + path
}
// A tempDir manages a temporary directory within a test.

View File

@@ -0,0 +1,8 @@
// Copyright 2025 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.
#include "textflag.h"
DATA ·x(SB)/8, $123
GLOBL ·x(SB), NOPTR, $8

View File

@@ -0,0 +1,11 @@
// Copyright 2025 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
var x uint64
func main() {
println(x)
}

View File

@@ -0,0 +1,8 @@
// Copyright 2025 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.
#include "textflag.h"
DATA ·x(SB)/8, $123
GLOBL ·x(SB), NOPTR, $8

View File

@@ -0,0 +1,20 @@
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "unsafe"
var x uint64
func main() {
bar(&x)
}
func bar(a *uint64) {
p := (*uint64)(unsafe.Add(unsafe.Pointer(a), 1*unsafe.Sizeof(uint64(1))))
if *p == 10 { // BOOM
println("its value is 10")
}
}

View File

@@ -886,8 +886,8 @@ func init() {
inputs: []regMask{buildReg("DI")},
clobbers: buildReg("DI"),
},
faultOnNilArg0: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// arg0 = address of memory to zero
@@ -924,10 +924,10 @@ func init() {
inputs: []regMask{buildReg("DI"), buildReg("SI")},
clobbers: buildReg("DI SI X0"), // uses X0 as a temporary
},
clobberFlags: true,
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
clobberFlags: true,
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
//faultOnNilArg1: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// arg0 = destination pointer

View File

@@ -536,8 +536,8 @@ func init() {
inputs: []regMask{buildReg("R20")},
clobbers: buildReg("R16 R17 R20 R30"),
},
faultOnNilArg0: true,
unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
},
// large zeroing
@@ -577,9 +577,9 @@ func init() {
inputs: []regMask{buildReg("R21"), buildReg("R20")},
clobbers: buildReg("R16 R17 R20 R21 R26 R30"),
},
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
//faultOnNilArg1: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// large move

View File

@@ -13777,11 +13777,10 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "DUFFZERO",
auxType: auxInt64,
argLen: 2,
faultOnNilArg0: true,
unsafePoint: true,
name: "DUFFZERO",
auxType: auxInt64,
argLen: 2,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 128}, // DI
@@ -13851,13 +13850,11 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "DUFFCOPY",
auxType: auxInt64,
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true,
name: "DUFFCOPY",
auxType: auxInt64,
argLen: 3,
clobberFlags: true,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 128}, // DI
@@ -22970,11 +22967,10 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "DUFFZERO",
auxType: auxInt64,
argLen: 2,
faultOnNilArg0: true,
unsafePoint: true,
name: "DUFFZERO",
auxType: auxInt64,
argLen: 2,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 1048576}, // R20
@@ -22996,12 +22992,10 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "DUFFCOPY",
auxType: auxInt64,
argLen: 3,
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true,
name: "DUFFCOPY",
auxType: auxInt64,
argLen: 3,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 2097152}, // R21

View File

@@ -1470,6 +1470,11 @@ func GetPPC64Shiftme(auxint int64) int64 {
// operation. Masks can also extend from the msb and wrap to
// the lsb too. That is, the valid masks are 32 bit strings
// of the form: 0..01..10..0 or 1..10..01..1 or 1...1
//
// Note: This ignores the upper 32 bits of the input. When a
// zero extended result is desired (e.g a 64 bit result), the
// user must verify the upper 32 bits are 0 and the mask is
// contiguous (that is, non-wrapping).
func isPPC64WordRotateMask(v64 int64) bool {
// Isolate rightmost 1 (if none 0) and add.
v := uint32(v64)
@@ -1480,6 +1485,16 @@ func isPPC64WordRotateMask(v64 int64) bool {
return (v&vp == 0 || vn&vpn == 0) && v != 0
}
// Test if this mask is a valid, contiguous bitmask which can be
// represented by a RLWNM mask and also clears the upper 32 bits
// of the register.
func isPPC64WordRotateMaskNonWrapping(v64 int64) bool {
// Isolate rightmost 1 (if none 0) and add.
v := uint32(v64)
vp := (v & -v) + v
return (v&vp == 0) && v != 0 && uint64(uint32(v64)) == uint64(v64)
}
// Compress mask and shift into single value of the form
// me | mb<<8 | rotate<<16 | nbits<<24 where me and mb can
// be used to regenerate the input mask.
@@ -1589,7 +1604,7 @@ func mergePPC64AndSrdi(m, s int64) int64 {
if rv&uint64(mask) != 0 {
return 0
}
if !isPPC64WordRotateMask(mask) {
if !isPPC64WordRotateMaskNonWrapping(mask) {
return 0
}
return encodePPC64RotateMask((32-s)&31, mask, 32)
@@ -1604,7 +1619,7 @@ func mergePPC64AndSldi(m, s int64) int64 {
if rv&uint64(mask) != 0 {
return 0
}
if !isPPC64WordRotateMask(mask) {
if !isPPC64WordRotateMaskNonWrapping(mask) {
return 0
}
return encodePPC64RotateMask(s&31, mask, 32)

View File

@@ -114,7 +114,11 @@ func Init() {
fsys.Bind(Dir(), filepath.Join(cfg.GOROOT, "src/crypto/internal/fips140"))
}
if cfg.Experiment.BoringCrypto && Enabled() {
// ExperimentErr != nil if GOEXPERIMENT failed to parse. Typically
// cmd/go main will exit in this case, but it is allowed during
// toolchain selection, as the GOEXPERIMENT may be valid for the
// selected toolchain version.
if cfg.ExperimentErr == nil && cfg.Experiment.BoringCrypto && Enabled() {
base.Fatalf("go: cannot use GOFIPS140 with GOEXPERIMENT=boringcrypto")
}
}

View File

@@ -2534,7 +2534,6 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
var repoDir string
var vcsCmd *vcs.Cmd
var err error
const allowNesting = true
wantVCS := false
switch cfg.BuildBuildvcs {
@@ -2554,7 +2553,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
// (so the bootstrap toolchain packages don't even appear to be in GOROOT).
goto omitVCS
}
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting)
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "")
if err != nil && !errors.Is(err, os.ErrNotExist) {
setVCSError(err)
return
@@ -2577,10 +2576,11 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
}
if repoDir != "" && vcsCmd.Status != nil {
// Check that the current directory, package, and module are in the same
// repository. vcs.FromDir allows nested Git repositories, but nesting
// is not allowed for other VCS tools. The current directory may be outside
// p.Module.Dir when a workspace is used.
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting)
// repository. vcs.FromDir disallows nested VCS and multiple VCS in the
// same repository, unless the GODEBUG allowmultiplevcs is set. The
// current directory may be outside p.Module.Dir when a workspace is
// used.
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "")
if err != nil {
setVCSError(err)
return
@@ -2592,7 +2592,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
}
goto omitVCS
}
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "")
if err != nil {
setVCSError(err)
return

View File

@@ -230,7 +230,7 @@ func LookupLocal(ctx context.Context, path string) Repo {
return lookupLocalCache.Do(path, func() Repo {
return newCachingRepo(ctx, path, func(ctx context.Context) (Repo, error) {
repoDir, vcsCmd, err := vcs.FromDir(path, "", true)
repoDir, vcsCmd, err := vcs.FromDir(path, "")
if err != nil {
return nil, err
}

View File

@@ -8,6 +8,7 @@ import (
"bytes"
"errors"
"fmt"
"internal/godebug"
"internal/lazyregexp"
"internal/singleflight"
"io/fs"
@@ -839,11 +840,13 @@ type vcsPath struct {
schemelessRepo bool // if true, the repo pattern lacks a scheme
}
var allowmultiplevcs = godebug.New("allowmultiplevcs")
// FromDir inspects dir and its parents to determine the
// version control system and code repository to use.
// If no repository is found, FromDir returns an error
// equivalent to os.ErrNotExist.
func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cmd, err error) {
func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) {
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
dir = filepath.Clean(dir)
if srcRoot != "" {
@@ -857,21 +860,28 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm
for len(dir) > len(srcRoot) {
for _, vcs := range vcsList {
if isVCSRoot(dir, vcs.RootNames) {
// Record first VCS we find.
// If allowNesting is false (as it is in GOPATH), keep looking for
// repositories in parent directories and report an error if one is
// found to mitigate VCS injection attacks.
if vcsCmd == nil {
// Record first VCS we find.
vcsCmd = vcs
repoDir = dir
if allowNesting {
if allowmultiplevcs.Value() == "1" {
allowmultiplevcs.IncNonDefault()
return repoDir, vcsCmd, nil
}
// If allowmultiplevcs is not set, keep looking for
// repositories in current and parent directories and report
// an error if one is found to mitigate VCS injection
// attacks.
continue
}
// Otherwise, we have one VCS inside a different VCS.
return "", nil, fmt.Errorf("directory %q uses %s, but parent %q uses %s",
repoDir, vcsCmd.Cmd, dir, vcs.Cmd)
if vcsCmd == vcsGit && vcs == vcsGit {
// Nested Git is allowed, as this is how things like
// submodules work. Git explicitly protects against
// injection against itself.
continue
}
return "", nil, fmt.Errorf("multiple VCS detected: %s in %q, and %s in %q",
vcsCmd.Cmd, repoDir, vcs.Cmd, dir)
}
}

View File

@@ -239,7 +239,7 @@ func TestFromDir(t *testing.T) {
}
wantRepoDir := filepath.Dir(dir)
gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false)
gotRepoDir, gotVCS, err := FromDir(dir, tempDir)
if err != nil {
t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
continue

View File

@@ -0,0 +1,54 @@
# To avoid VCS injection attacks, we should not accept multiple different VCS metadata
# folders within a single module (either in the same directory, or nested in different
# directories.)
#
# This behavior should be disabled by setting the allowmultiplevcs GODEBUG.
[short] skip
[!git] skip
cd samedir
exec git init .
# Without explicitly requesting buildvcs, the go command should silently continue
# without determining the correct VCS.
go test -c -o $devnull .
# If buildvcs is explicitly requested, we expect the go command to fail
! go test -buildvcs -c -o $devnull .
stderr '^error obtaining VCS status: multiple VCS detected:'
env GODEBUG=allowmultiplevcs=1
go test -buildvcs -c -o $devnull .
env GODEBUG=
cd ../nested
exec git init .
# cd a
go test -c -o $devnull ./a
! go test -buildvcs -c -o $devnull ./a
stderr '^error obtaining VCS status: multiple VCS detected:'
# allowmultiplevcs doesn't disable the check that the current directory, package, and
# module are in the same repository.
env GODEBUG=allowmultiplevcs=1
! go test -buildvcs -c -o $devnull ./a
stderr '^error obtaining VCS status: main package is in repository'
-- samedir/go.mod --
module example
go 1.18
-- samedir/example.go --
package main
-- samedir/.bzr/test --
hello
-- nested/go.mod --
module example
go 1.18
-- nested/a/example.go --
package main
-- nested/a/.bzr/test --
hello

View File

@@ -9,25 +9,35 @@ cd root
go mod init example.com/root
exec git init
# Nesting repositories in parent directories are ignored, as the current
# directory main package, and containing main module are in the same repository.
# This is an error in GOPATH mode (to prevent VCS injection), but for modules,
# we assume users have control over repositories they've checked out.
# Nesting repositories in parent directories are an error, to prevent VCS injection.
# This can be disabled with the allowmultiplevcs GODEBUG.
mkdir hgsub
cd hgsub
exec hg init
cp ../../main.go main.go
! go build
stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$'
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
env GODEBUG=allowmultiplevcs=1
! go build
stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$'
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
go build -buildvcs=false
env GODEBUG=
go mod init example.com/root/hgsub
! go build
stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$'
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
env GODEBUG=allowmultiplevcs=1
go build
env GODEBUG=
cd ..
# It's an error to build a package from a nested Git repository if the package
# is in a separate repository from the current directory or from the module
# root directory.
# root directory. Otherwise nested Git repositories are allowed, as this is
# how Git implements submodules (and protects against Git based VCS injection.)
mkdir gitsub
cd gitsub
exec git init

View File

@@ -253,6 +253,12 @@ type Loader struct {
WasmExports []Sym
// sizeFixups records symbols that we need to fix up the size
// after loading. It is very rarely needed, only for a DATA symbol
// and a BSS symbol with the same name, and the BSS symbol has
// larger size.
sizeFixups []symAndSize
flags uint32
strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
@@ -469,18 +475,17 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
// In summary, the "overwrite" variable and the final result are
//
// new sym old sym result
// ---------------------------------------------
// -------------------------------------------------------
// TEXT BSS new wins
// DATA DATA ERROR
// DATA lg/eq BSS sm/eq new wins
// DATA small BSS large ERROR
// BSS large DATA small ERROR
// DATA small BSS large merge: new with larger size
// BSS large DATA small merge: old with larger size
// BSS large BSS small new wins
// BSS sm/eq D/B lg/eq old wins
// BSS TEXT old wins
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
newtyp := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
oldIsText := oldtyp.IsText()
newIsText := newtyp.IsText()
oldHasContent := oldr.DataSize(oldli) != 0
newHasContent := r.DataSize(li) != 0
@@ -488,12 +493,28 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
newIsBSS := newtyp.IsData() && !newHasContent
switch {
case newIsText && oldIsBSS,
newHasContent && oldIsBSS && sz >= oldsz,
newHasContent && oldIsBSS,
newIsBSS && oldIsBSS && sz > oldsz:
// new symbol overwrites old symbol.
l.objSyms[oldi] = objSym{r.objidx, li}
case newIsBSS && (oldsz >= sz || oldIsText):
if oldsz > sz {
// If the BSS symbol has a larger size, expand the data
// symbol's size so access from the BSS side cannot overrun.
// It is hard to modify the symbol size until all Go objects
// (potentially read-only) are loaded, so we record it in
// a fixup table and apply them later. This is very rare.
// One case is a global variable with a Go declaration and an
// assembly definition, which typically have the same size,
// but in ASAN mode the Go declaration has a larger size due
// to the inserted red zone.
l.sizeFixups = append(l.sizeFixups, symAndSize{oldi, uint32(oldsz)})
}
case newIsBSS:
// old win, just ignore the new symbol.
if sz > oldsz {
// See the comment above for sizeFixups.
l.sizeFixups = append(l.sizeFixups, symAndSize{oldi, uint32(sz)})
}
default:
log.Fatalf("duplicated definition of symbol %s, from %s (type %s size %d) and %s (type %s size %d)", name, r.unit.Lib.Pkg, newtyp, sz, oldr.unit.Lib.Pkg, oldtyp, oldsz)
}
@@ -2285,6 +2306,10 @@ func (l *Loader) LoadSyms(arch *sys.Arch) {
st.preloadSyms(r, hashedDef)
st.preloadSyms(r, nonPkgDef)
}
for _, sf := range l.sizeFixups {
pp := l.cloneToExternal(sf.sym)
pp.size = int64(sf.size)
}
for _, vr := range st.linknameVarRefs {
l.checkLinkname(vr.pkg, vr.name, vr.sym)
}
@@ -2490,7 +2515,7 @@ func topLevelSym(sname string, skind sym.SymKind) bool {
// a symbol originally discovered as part of an object file, it's
// easier to do this if we make the updates to an external symbol
// payload.
func (l *Loader) cloneToExternal(symIdx Sym) {
func (l *Loader) cloneToExternal(symIdx Sym) *extSymPayload {
if l.IsExternal(symIdx) {
panic("sym is already external, no need for clone")
}
@@ -2542,6 +2567,8 @@ func (l *Loader) cloneToExternal(symIdx Sym) {
// Some attributes were encoded in the object file. Copy them over.
l.SetAttrDuplicateOK(symIdx, r.Sym(li).Dupok())
l.SetAttrShared(symIdx, r.Shared())
return pp
}
// Copy the payload of symbol src to dst. Both src and dst must be external