diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go index c9e9e5fe63..1cd8c2ab4a 100644 --- a/misc/cgo/testcshared/cshared_test.go +++ b/misc/cgo/testcshared/cshared_test.go @@ -317,30 +317,46 @@ func createHeaders() error { if err != nil { return fmt.Errorf("unable to find dlltool path: %v\n%s\n", err, out) } - args := []string{strings.TrimSpace(string(out)), "-D", args[6], "-l", libgoname, "-d", "libgo.def"} - - // This is an unfortunate workaround for https://github.com/mstorsjo/llvm-mingw/issues/205 in which - // we basically reimplement the contents of the dlltool.sh wrapper: https://git.io/JZFlU - dlltoolContents, err := os.ReadFile(args[0]) - if err != nil { - return fmt.Errorf("unable to read dlltool: %v\n", err) - } - if bytes.HasPrefix(dlltoolContents, []byte("#!/bin/sh")) && bytes.Contains(dlltoolContents, []byte("llvm-dlltool")) { - base, name := filepath.Split(args[0]) - args[0] = filepath.Join(base, "llvm-dlltool") - var machine string - switch prefix, _, _ := strings.Cut(name, "-"); prefix { - case "i686": - machine = "i386" - case "x86_64": - machine = "i386:x86-64" - case "armv7": - machine = "arm" - case "aarch64": - machine = "arm64" + dlltoolpath := strings.TrimSpace(string(out)) + if filepath.Ext(dlltoolpath) == "" { + // Some compilers report slash-separated paths without extensions + // instead of ordinary Windows paths. + // Try to find the canonical name for the path. + if lp, err := exec.LookPath(dlltoolpath); err == nil { + dlltoolpath = lp } - if len(machine) > 0 { - args = append(args, "-m", machine) + } + + args := []string{dlltoolpath, "-D", args[6], "-l", libgoname, "-d", "libgo.def"} + + if filepath.Ext(dlltoolpath) == "" { + // This is an unfortunate workaround for + // https://github.com/mstorsjo/llvm-mingw/issues/205 in which + // we basically reimplement the contents of the dlltool.sh + // wrapper: https://git.io/JZFlU. + // TODO(thanm): remove this workaround once we can upgrade + // the compilers on the windows-arm64 builder. + dlltoolContents, err := os.ReadFile(args[0]) + if err != nil { + return fmt.Errorf("unable to read dlltool: %v\n", err) + } + if bytes.HasPrefix(dlltoolContents, []byte("#!/bin/sh")) && bytes.Contains(dlltoolContents, []byte("llvm-dlltool")) { + base, name := filepath.Split(args[0]) + args[0] = filepath.Join(base, "llvm-dlltool") + var machine string + switch prefix, _, _ := strings.Cut(name, "-"); prefix { + case "i686": + machine = "i386" + case "x86_64": + machine = "i386:x86-64" + case "armv7": + machine = "arm" + case "aarch64": + machine = "arm64" + } + if len(machine) > 0 { + args = append(args, "-m", machine) + } } } diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index dc5639812a..79d27c3e37 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -577,8 +577,23 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) { switch e.Tag { case dwarf.TagVariable: name, _ := e.Val(dwarf.AttrName).(string) + // As of https://reviews.llvm.org/D123534, clang + // now emits DW_TAG_variable DIEs that have + // no name (so as to be able to describe the + // type and source locations of constant strings + // like the second arg in the call below: + // + // myfunction(42, "foo") + // + // If a var has no name we won't see attempts to + // refer to it via "C.", so skip these vars + // + // See issue 53000 for more context. + if name == "" { + break + } typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset) - if name == "" || typOff == 0 { + if typOff == 0 { if e.Val(dwarf.AttrSpecification) != nil { // Since we are reading all the DWARF, // assume we will see the variable elsewhere. diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 09e70ad13b..ad99960078 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -316,9 +316,9 @@ (FCMPD x (FMOVDconst [0])) => (FCMPD0 x) (FCMPD (FMOVDconst [0]) x) => (InvertFlags (FCMPD0 x)) -// CSEL needs a flag-generating argument. Synthesize a CMPW if necessary. +// CSEL needs a flag-generating argument. Synthesize a TSTW if necessary. (CondSelect x y boolval) && flagArg(boolval) != nil => (CSEL [boolval.Op] x y flagArg(boolval)) -(CondSelect x y boolval) && flagArg(boolval) == nil => (CSEL [OpARM64NotEqual] x y (CMPWconst [0] boolval)) +(CondSelect x y boolval) && flagArg(boolval) == nil => (CSEL [OpARM64NotEqual] x y (TSTWconst [1] boolval)) (OffPtr [off] ptr:(SP)) && is32Bit(off) => (MOVDaddr [int32(off)] ptr) (OffPtr [off] ptr) => (ADDconst [off] ptr) diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64.rules b/src/cmd/compile/internal/ssa/gen/MIPS64.rules index 292ff2fc79..0d6d30fa4c 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS64.rules @@ -392,7 +392,8 @@ (AtomicAdd(32|64) ...) => (LoweredAtomicAdd(32|64) ...) -(AtomicCompareAndSwap(32|64) ...) => (LoweredAtomicCas(32|64) ...) +(AtomicCompareAndSwap32 ptr old new mem) => (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) +(AtomicCompareAndSwap64 ...) => (LoweredAtomicCas64 ...) // checks (NilCheck ...) => (LoweredNilCheck ...) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index a90a3d0937..f83ed78bab 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -562,9 +562,9 @@ ((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(XOR x y)) yes no) && z.Uses == 1 => ((EQ|NE|LT|LE|GT|GE) (XORCC x y) yes no) // Only lower after bool is lowered. It should always lower. This helps ensure the folding below happens reliably. -(CondSelect x y bool) && flagArg(bool) == nil => (ISEL [6] x y (CMPWconst [0] bool)) +(CondSelect x y bool) && flagArg(bool) == nil => (ISEL [6] x y (Select1 (ANDCCconst [1] bool))) // Fold any CR -> GPR -> CR transfers when applying the above rule. -(ISEL [6] x y (CMPWconst [0] (ISELB [c] one cmp))) => (ISEL [c] x y cmp) +(ISEL [6] x y (Select1 (ANDCCconst [1] (ISELB [c] one cmp)))) => (ISEL [c] x y cmp) // Lowering loads (Load ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVDload ptr mem) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 59d8af1a9d..d18cbcc787 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -11,8 +11,8 @@ import "strings" // Notes: // - Less-than-64-bit integer types live in the low portion of registers. -// For now, the upper portion is junk; sign/zero-extension might be optimized in the future, but not yet. -// - Boolean types are zero or 1; stored in a byte, but loaded with AMOVBZ so the upper bytes of a register are zero. +// The upper portion is junk. +// - Boolean types are zero or 1; stored in a byte, with upper bytes of the register containing junk. // - *const instructions may use a constant larger than the instruction can encode. // In this case the assembler expands to multiple instructions and uses tmp // register (R31). diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 7aea622c5e..acef3df389 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -568,7 +568,7 @@ (AtomicAnd32 ...) => (LoweredAtomicAnd32 ...) -(AtomicCompareAndSwap32 ...) => (LoweredAtomicCas32 ...) +(AtomicCompareAndSwap32 ptr old new mem) => (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) (AtomicCompareAndSwap64 ...) => (LoweredAtomicCas64 ...) (AtomicExchange32 ...) => (LoweredAtomicExchange32 ...) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 1ee25c2eee..ad1052f88d 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -23409,7 +23409,7 @@ func rewriteValueARM64_OpCondSelect(v *Value) bool { } // match: (CondSelect x y boolval) // cond: flagArg(boolval) == nil - // result: (CSEL [OpARM64NotEqual] x y (CMPWconst [0] boolval)) + // result: (CSEL [OpARM64NotEqual] x y (TSTWconst [1] boolval)) for { x := v_0 y := v_1 @@ -23419,8 +23419,8 @@ func rewriteValueARM64_OpCondSelect(v *Value) bool { } v.reset(OpARM64CSEL) v.AuxInt = opToAuxInt(OpARM64NotEqual) - v0 := b.NewValue0(v.Pos, OpARM64CMPWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(0) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(1) v0.AddArg(boolval) v.AddArg3(x, y, v0) return true diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go index 1fbd556b5c..6a0fd3ad6e 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS64.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go @@ -52,8 +52,7 @@ func rewriteValueMIPS64(v *Value) bool { v.Op = OpMIPS64LoweredAtomicAdd64 return true case OpAtomicCompareAndSwap32: - v.Op = OpMIPS64LoweredAtomicCas32 - return true + return rewriteValueMIPS64_OpAtomicCompareAndSwap32(v) case OpAtomicCompareAndSwap64: v.Op = OpMIPS64LoweredAtomicCas64 return true @@ -697,6 +696,27 @@ func rewriteValueMIPS64_OpAddr(v *Value) bool { return true } } +func rewriteValueMIPS64_OpAtomicCompareAndSwap32(v *Value) bool { + v_3 := v.Args[3] + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicCompareAndSwap32 ptr old new mem) + // result: (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) + for { + ptr := v_0 + old := v_1 + new := v_2 + mem := v_3 + v.reset(OpMIPS64LoweredAtomicCas32) + v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64) + v0.AddArg(old) + v.AddArg4(ptr, v0, new, mem) + return true + } +} func rewriteValueMIPS64_OpAvg64u(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 5a28b9d4f7..c7bcc248fc 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -1167,9 +1167,10 @@ func rewriteValuePPC64_OpCondSelect(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block + typ := &b.Func.Config.Types // match: (CondSelect x y bool) // cond: flagArg(bool) == nil - // result: (ISEL [6] x y (CMPWconst [0] bool)) + // result: (ISEL [6] x y (Select1 (ANDCCconst [1] bool))) for { x := v_0 y := v_1 @@ -1179,9 +1180,11 @@ func rewriteValuePPC64_OpCondSelect(v *Value) bool { } v.reset(OpPPC64ISEL) v.AuxInt = int32ToAuxInt(6) - v0 := b.NewValue0(v.Pos, OpPPC64CMPWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(0) - v0.AddArg(bool) + v0 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags) + v1 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.NewTuple(typ.Int, types.TypeFlags)) + v1.AuxInt = int64ToAuxInt(1) + v1.AddArg(bool) + v0.AddArg(v1) v.AddArg3(x, y, v0) return true } @@ -5895,7 +5898,7 @@ func rewriteValuePPC64_OpPPC64ISEL(v *Value) bool { v.AddArg(y) return true } - // match: (ISEL [6] x y (CMPWconst [0] (ISELB [c] one cmp))) + // match: (ISEL [6] x y (Select1 (ANDCCconst [1] (ISELB [c] one cmp)))) // result: (ISEL [c] x y cmp) for { if auxIntToInt32(v.AuxInt) != 6 { @@ -5903,15 +5906,19 @@ func rewriteValuePPC64_OpPPC64ISEL(v *Value) bool { } x := v_0 y := v_1 - if v_2.Op != OpPPC64CMPWconst || auxIntToInt32(v_2.AuxInt) != 0 { + if v_2.Op != OpSelect1 { break } v_2_0 := v_2.Args[0] - if v_2_0.Op != OpPPC64ISELB { + if v_2_0.Op != OpPPC64ANDCCconst || auxIntToInt64(v_2_0.AuxInt) != 1 { break } - c := auxIntToInt32(v_2_0.AuxInt) - cmp := v_2_0.Args[1] + v_2_0_0 := v_2_0.Args[0] + if v_2_0_0.Op != OpPPC64ISELB { + break + } + c := auxIntToInt32(v_2_0_0.AuxInt) + cmp := v_2_0_0.Args[1] v.reset(OpPPC64ISEL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, cmp) diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 6828d97ff8..b277979061 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -61,8 +61,7 @@ func rewriteValueRISCV64(v *Value) bool { case OpAtomicAnd8: return rewriteValueRISCV64_OpAtomicAnd8(v) case OpAtomicCompareAndSwap32: - v.Op = OpRISCV64LoweredAtomicCas32 - return true + return rewriteValueRISCV64_OpAtomicCompareAndSwap32(v) case OpAtomicCompareAndSwap64: v.Op = OpRISCV64LoweredAtomicCas64 return true @@ -765,6 +764,27 @@ func rewriteValueRISCV64_OpAtomicAnd8(v *Value) bool { return true } } +func rewriteValueRISCV64_OpAtomicCompareAndSwap32(v *Value) bool { + v_3 := v.Args[3] + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicCompareAndSwap32 ptr old new mem) + // result: (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) + for { + ptr := v_0 + old := v_1 + new := v_2 + mem := v_3 + v.reset(OpRISCV64LoweredAtomicCas32) + v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64) + v0.AddArg(old) + v.AddArg4(ptr, v0, new, mem) + return true + } +} func rewriteValueRISCV64_OpAtomicOr8(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] diff --git a/src/cmd/go/testdata/script/mod_replace_gopkgin.txt b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt index df752d9716..8cb034c36c 100644 --- a/src/cmd/go/testdata/script/mod_replace_gopkgin.txt +++ b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt @@ -4,6 +4,9 @@ # even if there is an explicit go.mod file containing the # gopkg.in path. +skip 'skipping test that depends on an unreliable third-party server; see https://go.dev/issue/54503' + # TODO(#54043): Make this test hermetic and re-enable it. + [short] skip [!net] skip [!exec:git] skip diff --git a/src/cmd/go/testdata/script/trampoline_reuse_test.txt b/src/cmd/go/testdata/script/trampoline_reuse_test.txt new file mode 100644 index 0000000000..bca897c16d --- /dev/null +++ b/src/cmd/go/testdata/script/trampoline_reuse_test.txt @@ -0,0 +1,100 @@ +# Verify PPC64 does not reuse a trampoline which is too far away. +# This tests an edge case where the direct call relocation addend should +# be ignored when computing the distance from the direct call to the +# already placed trampoline +[short] skip +[!ppc64] [!ppc64le] skip +[aix] skip + +# Note, this program does not run. Presumably, 'DWORD $0' is simpler to +# assembly 2^26 or so times. +# +# We build something which should be laid out as such: +# +# bar.Bar +# main.Func1 +# bar.Bar+400-tramp0 +# main.BigAsm +# main.Func2 +# bar.Bar+400-tramp1 +# +# bar.Bar needs to be placed far enough away to generate relocations +# from main package calls. and main.Func1 and main.Func2 are placed +# a bit more than the direct call limit apart, but not more than 0x400 +# bytes beyond it (to verify the reloc calc). + +go build + +-- go.mod -- + +module foo + +go 1.19 + +-- main.go -- + +package main + +import "foo/bar" + +func Func1() + +func main() { + Func1() + bar.Bar2() +} + +-- foo.s -- + +TEXT main·Func1(SB),0,$0-0 + CALL bar·Bar+0x400(SB) + CALL main·BigAsm(SB) +// A trampoline will be placed here to bar.Bar + +// This creates a gap sufficiently large to prevent trampoline reuse +#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; +#define NOP256 NOP64 NOP64 NOP64 NOP64 +#define NOP2S10 NOP256 NOP256 NOP256 NOP256 +#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10 +#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12 +#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14 +#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16 +#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18 +#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20 +#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22 +#define BIGNOP NOP2S24 NOP2S24 +TEXT main·BigAsm(SB),0,$0-0 + // Fill to the direct call limit so Func2 must generate a new trampoline. + // As the implicit trampoline above is just barely unreachable. + BIGNOP + MOVD $main·Func2(SB), R3 + +TEXT main·Func2(SB),0,$0-0 + CALL bar·Bar+0x400(SB) +// Another trampoline should be placed here. + +-- bar/bar.s -- + +#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; +#define NOP256 NOP64 NOP64 NOP64 NOP64 +#define NOP2S10 NOP256 NOP256 NOP256 NOP256 +#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10 +#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12 +#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14 +#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16 +#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18 +#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20 +#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22 +#define BIGNOP NOP2S24 NOP2S24 NOP2S10 +// A very big not very interesting function. +TEXT bar·Bar(SB),0,$0-0 + BIGNOP + +-- bar/bar.go -- + +package bar + +func Bar() + +func Bar2() { +} diff --git a/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt b/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt deleted file mode 100644 index dcf97d7c44..0000000000 --- a/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt +++ /dev/null @@ -1,105 +0,0 @@ -# This test checks that VCS information is stamped into Go binaries even when -# the current commit is signed and the use has configured git to display commit -# signatures. - -[!exec:git] skip -[!exec:gpg] skip -[short] skip -env GOBIN=$GOPATH/bin -env GNUPGHOME=$WORK/.gpupg -mkdir $GNUPGHOME -chmod 0700 $GNUPGHOME - -# Create GPG key -exec gpg --batch --passphrase '' --quick-generate-key gopher@golang.org -exec gpg --list-secret-keys --with-colons gopher@golang.org -cp stdout keyinfo.txt -go run extract_key_id.go keyinfo.txt -cp stdout keyid.txt - -# Initialize repo -cd repo/ -exec git init -exec git config user.email gopher@golang.org -exec git config user.name 'J.R. Gopher' -exec git config --add log.showSignature true -go run ../configure_signing_key.go ../keyid.txt - -# Create signed commit -cd a -exec git add -A -exec git commit -m 'initial commit' --gpg-sign -exec git log - -# Verify commit signature does not interfere with versioning -go install -go version -m $GOBIN/a -stdout '^\tbuild\tvcs\.revision=' -stdout '^\tbuild\tvcs\.time=' -stdout '^\tbuild\tvcs\.modified=false$' - --- repo/README -- -Far out in the uncharted backwaters of the unfashionable end of the western -spiral arm of the Galaxy lies a small, unregarded yellow sun. --- repo/a/go.mod -- -module example.com/a - -go 1.18 --- repo/a/a.go -- -package main - -func main() {} - --- extract_key_id.go -- -package main - -import "fmt" -import "io/ioutil" -import "os" -import "strings" - -func main() { - err := run(os.Args[1]) - if err != nil { - panic(err) - } -} - -func run(keyInfoFilePath string) error { - contents, err := ioutil.ReadFile(keyInfoFilePath) - if err != nil { - return err - } - lines := strings.Split(string(contents), "\n") - for _, line := range lines { - fields := strings.Split(line, ":") - if fields[0] == "sec" { - fmt.Print(fields[4]) - return nil - } - } - return fmt.Errorf("key ID not found in: %s", keyInfoFilePath) -} - --- configure_signing_key.go -- -package main - -import "io/ioutil" -import "os" -import "os/exec" - -func main() { - err := run(os.Args[1]) - if err != nil { - panic(err) - } -} - -func run(keyIdFilePath string) error { - keyId, err := ioutil.ReadFile(keyIdFilePath) - if err != nil { - return err - } - gitCmd := exec.Command("git", "config", "user.signingKey", string(keyId)) - return gitCmd.Run() -} diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 73c2718a33..879adaa965 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -809,8 +809,9 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { if ldr.SymValue(tramp) == 0 { break } - - t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + // Note, the trampoline is always called directly. The addend of the original relocation is accounted for in the + // trampoline itself. + t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off())) // With internal linking, the trampoline can be used if it is not too far. // With external linking, the trampoline must be in this section for it to be reused. diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index 75c212910b..2b20b52dc6 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -184,6 +184,13 @@ func CFErrorCopyDescription(errRef CFRef) CFRef { } func x509_CFErrorCopyDescription_trampoline() +//go:cgo_import_dynamic x509_CFErrorGetCode CFErrorGetCode "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFErrorGetCode(errRef CFRef) int { + return int(syscall(abi.FuncPCABI0(x509_CFErrorGetCode_trampoline), uintptr(errRef), 0, 0, 0, 0, 0)) +} +func x509_CFErrorGetCode_trampoline() + //go:cgo_import_dynamic x509_CFStringCreateExternalRepresentation CFStringCreateExternalRepresentation "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFStringCreateExternalRepresentation(strRef CFRef) CFRef { diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s index d69f72f795..49cd084467 100644 --- a/src/crypto/x509/internal/macos/corefoundation.s +++ b/src/crypto/x509/internal/macos/corefoundation.s @@ -37,5 +37,7 @@ TEXT ·x509_CFDataCreate_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFDataCreate(SB) TEXT ·x509_CFErrorCopyDescription_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFErrorCopyDescription(SB) +TEXT ·x509_CFErrorGetCode_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFErrorGetCode(SB) TEXT ·x509_CFStringCreateExternalRepresentation_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFStringCreateExternalRepresentation(SB) diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go index ef64bda49f..0b7958eaa2 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -8,7 +8,6 @@ package macOS import ( "errors" - "fmt" "internal/abi" "strconv" "unsafe" @@ -51,6 +50,15 @@ const ( SecTrustSettingsDomainSystem ) +const ( + // various macOS error codes that can be returned from + // SecTrustEvaluateWithError that we can map to Go cert + // verification error types. + ErrSecCertificateExpired = -67818 + ErrSecHostNameMismatch = -67602 + ErrSecNotTrusted = -67843 +) + type OSStatus struct { call string status int32 @@ -190,17 +198,18 @@ func x509_SecTrustGetResult_trampoline() //go:cgo_import_dynamic x509_SecTrustEvaluateWithError SecTrustEvaluateWithError "/System/Library/Frameworks/Security.framework/Versions/A/Security" -func SecTrustEvaluateWithError(trustObj CFRef) error { +func SecTrustEvaluateWithError(trustObj CFRef) (int, error) { var errRef CFRef ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluateWithError_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&errRef)), 0, 0, 0, 0) if int32(ret) != 1 { errStr := CFErrorCopyDescription(errRef) - err := fmt.Errorf("x509: %s", CFStringToString(errStr)) + err := errors.New(CFStringToString(errStr)) + errCode := CFErrorGetCode(errRef) CFRelease(errRef) CFRelease(errStr) - return err + return errCode, err } - return nil + return 0, nil } func x509_SecTrustEvaluateWithError_trampoline() diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index ad365f577e..c35885ace8 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -7,6 +7,7 @@ package x509 import ( macOS "crypto/x509/internal/macos" "errors" + "fmt" ) func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { @@ -54,8 +55,17 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate // always enforce its SCT requirements, and there are still _some_ people // using TLS or OCSP for that. - if err := macOS.SecTrustEvaluateWithError(trustObj); err != nil { - return nil, err + if ret, err := macOS.SecTrustEvaluateWithError(trustObj); err != nil { + switch ret { + case macOS.ErrSecCertificateExpired: + return nil, CertificateInvalidError{c, Expired, err.Error()} + case macOS.ErrSecHostNameMismatch: + return nil, HostnameError{c, opts.DNSName} + case macOS.ErrSecNotTrusted: + return nil, UnknownAuthorityError{Cert: c} + default: + return nil, fmt.Errorf("x509: %s", err) + } } chain := [][]*Certificate{{}} diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go index 90a464f624..299cecf556 100644 --- a/src/crypto/x509/root_darwin_test.go +++ b/src/crypto/x509/root_darwin_test.go @@ -42,23 +42,23 @@ func TestPlatformVerifier(t *testing.T) { { name: "expired leaf", host: "expired.badssl.com", - expectedErr: "x509: “*.badssl.com” certificate is expired", + expectedErr: "x509: certificate has expired or is not yet valid: “*.badssl.com” certificate is expired", }, { name: "wrong host for leaf", host: "wrong.host.badssl.com", verifyName: "wrong.host.badssl.com", - expectedErr: "x509: “*.badssl.com” certificate name does not match input", + expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com", }, { name: "self-signed leaf", host: "self-signed.badssl.com", - expectedErr: "x509: “*.badssl.com” certificate is not trusted", + expectedErr: "x509: certificate signed by unknown authority", }, { name: "untrusted root", host: "untrusted-root.badssl.com", - expectedErr: "x509: “BadSSL Untrusted Root Certificate Authority” certificate is not trusted", + expectedErr: "x509: certificate signed by unknown authority", }, { name: "revoked leaf", @@ -74,7 +74,7 @@ func TestPlatformVerifier(t *testing.T) { name: "expired leaf (custom time)", host: "google.com", verifyTime: time.Time{}.Add(time.Hour), - expectedErr: "x509: “*.google.com” certificate is expired", + expectedErr: "x509: certificate has expired or is not yet valid: “*.google.com” certificate is expired", }, { name: "valid chain (custom time)", diff --git a/src/go.mod b/src/go.mod index 4613bb6825..e11c6d7df8 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 - golang.org/x/net v0.0.0-20220907013725-0a43f88f7ef0 + golang.org/x/net v0.0.0-20221214163811-6143a133e5c9 ) require ( diff --git a/src/go.sum b/src/go.sum index 07cb8d82d5..d2bfed64dc 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,7 +1,7 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20220907013725-0a43f88f7ef0 h1:XXaSUSplyi6wsRNJGB7vUBvDjbxc8UPYBsf9ukBQ3KA= -golang.org/x/net v0.0.0-20220907013725-0a43f88f7ef0/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20221214163811-6143a133e5c9 h1:gcbGP3ZkgsHGpX/48qvg7Q/YmTtzZRWc/zpvN8XGSBg= +golang.org/x/net v0.0.0-20221214163811-6143a133e5c9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y= diff --git a/src/internal/poll/sock_cloexec.go b/src/internal/poll/sock_cloexec.go index d849fda0b0..4c70abd9b1 100644 --- a/src/internal/poll/sock_cloexec.go +++ b/src/internal/poll/sock_cloexec.go @@ -5,7 +5,7 @@ // This file implements accept for platforms that provide a fast path for // setting SetNonblock and CloseOnExec. -//go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd +//go:build dragonfly || freebsd || illumos || (linux && !arm) || netbsd || openbsd package poll diff --git a/src/internal/poll/sock_cloexec_accept.go b/src/internal/poll/sock_cloexec_accept.go new file mode 100644 index 0000000000..4b86de59e0 --- /dev/null +++ b/src/internal/poll/sock_cloexec_accept.go @@ -0,0 +1,51 @@ +// Copyright 2013 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. + +// This file implements accept for platforms that provide a fast path for +// setting SetNonblock and CloseOnExec, but don't necessarily have accept4. +// This is the code we used for accept in Go 1.17 and earlier. +// On Linux the accept4 system call was introduced in 2.6.28 kernel, +// and our minimum requirement is 2.6.32, so we simplified the function. +// Unfortunately, on ARM accept4 wasn't added until 2.6.36, so for ARM +// only we continue using the older code. + +//go:build linux && arm + +package poll + +import "syscall" + +// Wrapper around the accept system call that marks the returned file +// descriptor as nonblocking and close-on-exec. +func accept(s int) (int, syscall.Sockaddr, string, error) { + ns, sa, err := Accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) + switch err { + case nil: + return ns, sa, "", nil + default: // errors other than the ones listed + return -1, sa, "accept4", err + case syscall.ENOSYS: // syscall missing + case syscall.EINVAL: // some Linux use this instead of ENOSYS + case syscall.EACCES: // some Linux use this instead of ENOSYS + case syscall.EFAULT: // some Linux use this instead of ENOSYS + } + + // See ../syscall/exec_unix.go for description of ForkLock. + // It is probably okay to hold the lock across syscall.Accept + // because we have put fd.sysfd into non-blocking mode. + // However, a call to the File method will put it back into + // blocking mode. We can't take that risk, so no use of ForkLock here. + ns, sa, err = AcceptFunc(s) + if err == nil { + syscall.CloseOnExec(ns) + } + if err != nil { + return -1, nil, "accept", err + } + if err = syscall.SetNonblock(ns, true); err != nil { + CloseFunc(ns) + return -1, nil, "setnonblock", err + } + return ns, sa, "", nil +} diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 381f91c8ad..3a21ecac3d 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -5760,12 +5760,6 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead return nil, nil, sc.countError("bad_path_method", http2streamError(f.StreamID, http2ErrCodeProtocol)) } - bodyOpen := !f.StreamEnded() - if rp.method == "HEAD" && bodyOpen { - // HEAD requests can't have bodies - return nil, nil, sc.countError("head_body", http2streamError(f.StreamID, http2ErrCodeProtocol)) - } - rp.header = make(Header) for _, hf := range f.RegularFields() { rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value) @@ -5778,6 +5772,7 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead if err != nil { return nil, nil, err } + bodyOpen := !f.StreamEnded() if bodyOpen { if vv, ok := rp.header["Content-Length"]; ok { if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil { diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 655543c7d2..32e7f8ef99 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -49,21 +49,21 @@ var lookupGoogleSRVTests = []struct { cname, target string }{ { - "xmpp-server", "tcp", "google.com", + "ldap", "tcp", "google.com", "google.com.", "google.com.", }, { - "xmpp-server", "tcp", "google.com.", + "ldap", "tcp", "google.com.", "google.com.", "google.com.", }, // non-standard back door { - "", "", "_xmpp-server._tcp.google.com", + "", "", "_ldap._tcp.google.com", "google.com.", "google.com.", }, { - "", "", "_xmpp-server._tcp.google.com.", + "", "", "_ldap._tcp.google.com.", "google.com.", "google.com.", }, } @@ -71,10 +71,6 @@ var lookupGoogleSRVTests = []struct { var backoffDuration = [...]time.Duration{time.Second, 5 * time.Second, 30 * time.Second} func TestLookupGoogleSRV(t *testing.T) { - // TODO(mknyszek): Figure out next steps for this test. This is just - // a quick fix. - t.Skip("fails consistently due to an upstream DNS change; see #56707.") - t.Parallel() mustHaveExternalNetwork(t) @@ -635,10 +631,6 @@ func TestLookupDotsWithLocalSource(t *testing.T) { } func TestLookupDotsWithRemoteSource(t *testing.T) { - // TODO(mknyszek): Figure out next steps for this test. This is just - // a quick fix. - t.Skip("fails consistently due to an upstream DNS change; see #56707.") - if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { testenv.SkipFlaky(t, 27992) } @@ -709,16 +701,16 @@ func testDots(t *testing.T, mode string) { } } - cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com") + cname, srvs, err := LookupSRV("ldap", "tcp", "google.com") if err != nil { - t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode) + t.Errorf("LookupSRV(ldap, tcp, google.com): %v (mode=%v)", err, mode) } else { if !hasSuffixFold(cname, ".google.com.") { - t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode) + t.Errorf("LookupSRV(ldap, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode) } for _, srv := range srvs { if !hasSuffixFold(srv.Target, ".google.com.") { - t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned addrs=%v, want names ending in .google.com. with trailing dot (mode=%v)", srvString(srvs), mode) + t.Errorf("LookupSRV(ldap, tcp, google.com) returned addrs=%v, want names ending in .google.com. with trailing dot (mode=%v)", srvString(srvs), mode) break } } diff --git a/src/os/os_test.go b/src/os/os_test.go index 4124be13cc..3721e15027 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -252,9 +252,11 @@ func TestLstat(t *testing.T) { if !equal(sfname, dir.Name()) { t.Error("name should be ", sfname, "; is", dir.Name()) } - filesize := size(path, t) - if dir.Size() != filesize { - t.Error("size should be", filesize, "; is", dir.Size()) + if dir.Mode()&ModeSymlink == 0 { + filesize := size(path, t) + if dir.Size() != filesize { + t.Error("size should be", filesize, "; is", dir.Size()) + } } } diff --git a/src/runtime/internal/atomic/atomic_test.go b/src/runtime/internal/atomic/atomic_test.go index 2ae60b8507..2427bfd211 100644 --- a/src/runtime/internal/atomic/atomic_test.go +++ b/src/runtime/internal/atomic/atomic_test.go @@ -345,6 +345,36 @@ func TestBitwiseContended(t *testing.T) { } } +func TestCasRel(t *testing.T) { + const _magic = 0x5a5aa5a5 + var x struct { + before uint32 + i uint32 + after uint32 + o uint32 + n uint32 + } + + x.before = _magic + x.after = _magic + for j := 0; j < 32; j += 1 { + x.i = (1 << j) + 0 + x.o = (1 << j) + 0 + x.n = (1 << j) + 1 + if !atomic.CasRel(&x.i, x.o, x.n) { + t.Fatalf("should have swapped %#x %#x", x.o, x.n) + } + + if x.i != x.n { + t.Fatalf("wrong x.i after swap: x.i=%#x x.n=%#x", x.i, x.n) + } + + if x.before != _magic || x.after != _magic { + t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, _magic, _magic) + } + } +} + func TestStorepNoWB(t *testing.T) { var p [2]*int for i := range p { diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index f32020ca6c..f694d8ca35 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -546,21 +546,6 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { return nil, EAFNOSUPPORT } -func Accept(fd int) (nfd int, sa Sockaddr, err error) { - var rsa RawSockaddrAny - var len _Socklen = SizeofSockaddrAny - nfd, err = accept4(fd, &rsa, &len, 0) - if err != nil { - return - } - sa, err = anyToSockaddr(&rsa) - if err != nil { - Close(nfd) - nfd = 0 - } - return -} - func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny diff --git a/src/syscall/syscall_linux_accept.go b/src/syscall/syscall_linux_accept.go new file mode 100644 index 0000000000..2ba60f0636 --- /dev/null +++ b/src/syscall/syscall_linux_accept.go @@ -0,0 +1,32 @@ +// Copyright 2009 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. + +// We require Linux kernel version 2.6.32. The accept4 system call was +// added in version 2.6.28, so in general we can use accept4. +// Unfortunately, for ARM only, accept4 was added in version 2.6.36. +// Handle that case here, by using a copy of the Accept function that +// we used in Go 1.17. + +//go:build linux && arm + +package syscall + +func Accept(fd int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + // Try accept4 first for Android and newer kernels. + nfd, err = accept4(fd, &rsa, &len, 0) + if err == ENOSYS { + nfd, err = accept(fd, &rsa, &len) + } + if err != nil { + return + } + sa, err = anyToSockaddr(&rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} diff --git a/src/syscall/syscall_linux_accept4.go b/src/syscall/syscall_linux_accept4.go new file mode 100644 index 0000000000..74898672c0 --- /dev/null +++ b/src/syscall/syscall_linux_accept4.go @@ -0,0 +1,25 @@ +// Copyright 2009 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. + +// This file provides the Accept function used on all systems +// other than arm. See syscall_linux_accept.go for why. + +//go:build linux && !arm + +package syscall + +func Accept(fd int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + nfd, err = accept4(fd, &rsa, &len, 0) + if err != nil { + return + } + sa, err = anyToSockaddr(&rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 109a99e44a..157c1fe602 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -9,7 +9,7 @@ golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/internal/subtle -# golang.org/x/net v0.0.0-20220907013725-0a43f88f7ef0 +# golang.org/x/net v0.0.0-20221214163811-6143a133e5c9 ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts diff --git a/test/fixedbugs/issue57184.go b/test/fixedbugs/issue57184.go new file mode 100644 index 0000000000..1384b50be8 --- /dev/null +++ b/test/fixedbugs/issue57184.go @@ -0,0 +1,40 @@ +// run + +// Copyright 2022 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 ( + "log" + "reflect" + "sort" +) + +func main() { + const length = 257 + x := make([]int64, length) + for i := 0; i < length; i++ { + x[i] = int64(i) * 27644437 % int64(length) + } + + isLessStatic := func(i, j int) bool { + return x[i] < x[j] + } + + isLessReflect := reflect.MakeFunc(reflect.TypeOf(isLessStatic), func(args []reflect.Value) []reflect.Value { + i := args[0].Int() + j := args[1].Int() + b := x[i] < x[j] + return []reflect.Value{reflect.ValueOf(b)} + }).Interface().(func(i, j int) bool) + + sort.SliceStable(x, isLessReflect) + + for i := 0; i < length-1; i++ { + if x[i] >= x[i+1] { + log.Fatalf("not sorted! (length=%v, idx=%v)\n%v\n", length, i, x) + } + } +}