doc/go1.15.html | 37 +++++++++++++++++++++++--------------
misc/cgo/test/test.go | 13 +++++++++++++
misc/cgo/testshared/shared_test.go | 13 +++++++++++++
src/cmd/cgo/out.go | 4 +++-
src/cmd/compile/internal/amd64/ssa.go | 6 +++++-
src/cmd/compile/internal/ssa/addressingmodes.go | 17 +++++++++++++++++
src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 34 ++++++++++++++++++++++++++--------
src/cmd/compile/internal/ssa/opGen.go | 320 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/cmd/compile/internal/ssa/prove.go | 8 ++++++++
src/cmd/go.mod | 1 +
src/cmd/go.sum | 2 ++
src/cmd/go/internal/load/pkg.go | 29 ++++++++++++++++-------------
src/cmd/go/testdata/script/list_err_stack.txt | 27 +++++++++++++++++++++++++++
src/cmd/link/internal/ld/lib.go | 11 -----------
src/cmd/vendor/modules.txt | 3 ++-
src/crypto/ed25519/ed25519.go | 6 +-----
src/crypto/ed25519/ed25519_noasm.go | 15 ---------------
src/crypto/ed25519/ed25519_s390x.go | 51 ---------------------------------------------------
src/crypto/ed25519/ed25519_s390x.s | 161 -----------------------------------------------------
src/crypto/ed25519/ed25519_test.go | 44 +++++++-------------------------------------
src/encoding/binary/varint.go | 5 +++--
src/encoding/binary/varint_test.go | 18 ++++++++++++------
src/net/http/transport.go | 73 ++++++++++++++++++++++++++++++-----------------------
src/net/http/transport_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++
src/runtime/lockrank_off.go | 4 ++++
src/runtime/lockrank_on.go | 4 ++++
src/runtime/mpagealloc.go | 43 ++++++++++++++++++++++++++++++++-----------
src/runtime/mpagealloc_test.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/runtime/mranges.go | 19 +++++++++++++++++++
src/runtime/proc.go | 69 ++++++++++++++++++++++++++++++++++++++++-------------
src/runtime/race/README | 6 +++---
src/runtime/race/syso_test.go | 39 +++++++++++++++++++++++++++++++++++++++
src/sync/runtime2.go | 4 ++++
src/sync/runtime2_lockrank.go | 4 ++++
src/syscall/exec_linux.go | 2 +-
src/testing/testing.go | 6 +++---
test/codegen/memops.go | 23 +++++++++++++++++++++++
test/fixedbugs/issue40367.go | 41 +++++++++++++++++++++++++++++++++++++++++
test/prove.go | 6 ++++--
diff --git a/doc/go1.15.html b/doc/go1.15.html
index 0cbc9be60d659e4f81d2ad42edb90cc701207d89..17e442d4c60d430b76c8bf25b7cadb339224bfdf 100644
--- a/doc/go1.15.html
+++ b/doc/go1.15.html
@@ -386,6 +386,23 @@ Java's JNI types. See the cgo
documentation for more information.
+X.509 CommonName deprecation
+
+
+ The deprecated, legacy behavior of treating the CommonName
+ field on X.509 certificates as a host name when no Subject Alternative Names
+ are present is now disabled by default. It can be temporarily re-enabled by
+ adding the value x509ignoreCN=0 to the GODEBUG
+ environment variable.
+
+
+
+ Note that if the CommonName is an invalid host name, it's always
+ ignored, regardless of GODEBUG settings. Invalid names include
+ those with any characters other than letters, digits, hyphens and underscores,
+ and those with empty labels or trailing dots.
+
+
Minor changes to the library
@@ -523,15 +540,6 @@ digits, hyphens and underscores, those with empty labels, and names on
certificates with trailing dots.
-
- The deprecated, legacy behavior of treating the CommonName
- field as a hostname when no Subject Alternative Names are present is now
- disabled by default. It can be temporarily re-enabled by adding the value
- x509ignoreCN=0 to the GODEBUG environment
- variable. If the CommonName is an invalid hostname, it's
- always ignored.
-
-
The new CreateRevocationList
function and RevocationList type
@@ -647,8 +655,8 @@
- flag
-
- When the flag package sees -h or -help, and
- those flags are not defined, it now prints a usage message.
+ When the flag package sees -h or -help,
+ and those flags are not defined, it now prints a usage message.
If the FlagSet was created with
ExitOnError,
FlagSet.Parse would then
@@ -893,9 +901,9 @@
- runtime/pprof
-
- The goroutine profile includes the profile labels associated with each goroutine
- at the time of profiling. This feature is not yet implemented for the profile
- reported with debug=2.
+ The goroutine profile now includes the profile labels associated with each
+ goroutine at the time of profiling. This feature is not yet implemented for
+ the profile reported with debug=2.
@@ -926,6 +934,7 @@ The method
Map.Delete
is more efficient.
+
- syscall
diff --git a/misc/cgo/test/test.go b/misc/cgo/test/test.go
index 8c69ad91ac7924d0d1ad52f77776121cb9afa5ab..35bc3a1447592f5d8b999b7ab95ee3afaaad1ef4 100644
--- a/misc/cgo/test/test.go
+++ b/misc/cgo/test/test.go
@@ -901,6 +901,12 @@
// issue 38649
// Test that #define'd type aliases work.
#define netbsd_gid unsigned int
+
+// issue 40494
+// Inconsistent handling of tagged enum and union types.
+enum Enum40494 { X_40494 };
+union Union40494 { int x; };
+void issue40494(enum Enum40494 e, union Union40494* up) {}
*/
import "C"
@@ -2204,3 +2210,10 @@
// issue 39877
var issue39877 *C.void = nil
+
+// issue 40494
+// No runtime test; just make sure it compiles.
+
+func Issue40494() {
+ C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil))
+}
diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go
index f8dabbe7a01f2ced2c840375a37253a5f10abaff..5e0893784b69d74cca9350719c313748121c2230 100644
--- a/misc/cgo/testshared/shared_test.go
+++ b/misc/cgo/testshared/shared_test.go
@@ -462,6 +462,7 @@ goCmd(t, "install", "-linkshared", "./trivial")
run(t, "trivial executable", "../../bin/trivial")
AssertIsLinkedTo(t, "../../bin/trivial", soname)
AssertHasRPath(t, "../../bin/trivial", gorootInstallDir)
+ checkSize(t, "../../bin/trivial", 100000) // it is 19K on linux/amd64, 100K should be enough
}
// Build a trivial program in PIE mode that links against the shared runtime and check it runs.
@@ -470,6 +471,18 @@ goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "./trivial")
run(t, "trivial executable", "./trivial.pie")
AssertIsLinkedTo(t, "./trivial.pie", soname)
AssertHasRPath(t, "./trivial.pie", gorootInstallDir)
+ checkSize(t, "./trivial.pie", 100000) // it is 19K on linux/amd64, 100K should be enough
+}
+
+// Check that the file size does not exceed a limit.
+func checkSize(t *testing.T, f string, limit int64) {
+ fi, err := os.Stat(f)
+ if err != nil {
+ t.Fatalf("stat failed: %v", err)
+ }
+ if sz := fi.Size(); sz > limit {
+ t.Errorf("file too large: got %d, want <= %d", sz, limit)
+ }
}
// Build a division test program and check it runs.
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 6c221473e084d41fa2cb560e494c5473496147d9..4064f0ae41819cbc3e6bcca7f4963fe23a31b018 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -123,7 +123,9 @@ // so subsequent source code uses the same source info.
// Moreover, empty file name makes compile emit no source debug info at all.
var buf bytes.Buffer
noSourceConf.Fprint(&buf, fset, def.Go)
- if bytes.HasPrefix(buf.Bytes(), []byte("_Ctype_")) {
+ if bytes.HasPrefix(buf.Bytes(), []byte("_Ctype_")) ||
+ strings.HasPrefix(name, "_Ctype_enum_") ||
+ strings.HasPrefix(name, "_Ctype_union_") {
// This typedef is of the form `typedef a b` and should be an alias.
fmt.Fprintf(fgo2, "= ")
}
diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go
index 47cb422ab112ece0f8afa0936770c5e9c21caaff..9d8a0920b39ba78eceab1cceaf3cd4af7eb86418 100644
--- a/src/cmd/compile/internal/amd64/ssa.go
+++ b/src/cmd/compile/internal/amd64/ssa.go
@@ -874,7 +874,11 @@ case ssa.OpAMD64ADDLloadidx1, ssa.OpAMD64ADDLloadidx4, ssa.OpAMD64ADDLloadidx8, ssa.OpAMD64ADDQloadidx1, ssa.OpAMD64ADDQloadidx8,
ssa.OpAMD64SUBLloadidx1, ssa.OpAMD64SUBLloadidx4, ssa.OpAMD64SUBLloadidx8, ssa.OpAMD64SUBQloadidx1, ssa.OpAMD64SUBQloadidx8,
ssa.OpAMD64ANDLloadidx1, ssa.OpAMD64ANDLloadidx4, ssa.OpAMD64ANDLloadidx8, ssa.OpAMD64ANDQloadidx1, ssa.OpAMD64ANDQloadidx8,
ssa.OpAMD64ORLloadidx1, ssa.OpAMD64ORLloadidx4, ssa.OpAMD64ORLloadidx8, ssa.OpAMD64ORQloadidx1, ssa.OpAMD64ORQloadidx8,
- ssa.OpAMD64XORLloadidx1, ssa.OpAMD64XORLloadidx4, ssa.OpAMD64XORLloadidx8, ssa.OpAMD64XORQloadidx1, ssa.OpAMD64XORQloadidx8:
+ ssa.OpAMD64XORLloadidx1, ssa.OpAMD64XORLloadidx4, ssa.OpAMD64XORLloadidx8, ssa.OpAMD64XORQloadidx1, ssa.OpAMD64XORQloadidx8,
+ ssa.OpAMD64ADDSSloadidx1, ssa.OpAMD64ADDSSloadidx4, ssa.OpAMD64ADDSDloadidx1, ssa.OpAMD64ADDSDloadidx8,
+ ssa.OpAMD64SUBSSloadidx1, ssa.OpAMD64SUBSSloadidx4, ssa.OpAMD64SUBSDloadidx1, ssa.OpAMD64SUBSDloadidx8,
+ ssa.OpAMD64MULSSloadidx1, ssa.OpAMD64MULSSloadidx4, ssa.OpAMD64MULSDloadidx1, ssa.OpAMD64MULSDloadidx8,
+ ssa.OpAMD64DIVSSloadidx1, ssa.OpAMD64DIVSSloadidx4, ssa.OpAMD64DIVSDloadidx1, ssa.OpAMD64DIVSDloadidx8:
p := s.Prog(v.Op.Asm())
r, i := v.Args[1].Reg(), v.Args[2].Reg()
diff --git a/src/cmd/compile/internal/ssa/addressingmodes.go b/src/cmd/compile/internal/ssa/addressingmodes.go
index 78c979b7cb09f185ebb0205591fd9d515cf9fd4e..97a5ab4f031510cf81a7121891bbd13fa449c7f8 100644
--- a/src/cmd/compile/internal/ssa/addressingmodes.go
+++ b/src/cmd/compile/internal/ssa/addressingmodes.go
@@ -321,6 +321,23 @@ [2]Op{OpAMD64XORLconstmodify, OpAMD64LEAQ8}: OpAMD64XORLconstmodifyidx8,
[2]Op{OpAMD64XORQconstmodify, OpAMD64LEAQ1}: OpAMD64XORQconstmodifyidx1,
[2]Op{OpAMD64XORQconstmodify, OpAMD64LEAQ8}: OpAMD64XORQconstmodifyidx8,
+ [2]Op{OpAMD64ADDSSload, OpAMD64LEAQ1}: OpAMD64ADDSSloadidx1,
+ [2]Op{OpAMD64ADDSSload, OpAMD64LEAQ4}: OpAMD64ADDSSloadidx4,
+ [2]Op{OpAMD64ADDSDload, OpAMD64LEAQ1}: OpAMD64ADDSDloadidx1,
+ [2]Op{OpAMD64ADDSDload, OpAMD64LEAQ8}: OpAMD64ADDSDloadidx8,
+ [2]Op{OpAMD64SUBSSload, OpAMD64LEAQ1}: OpAMD64SUBSSloadidx1,
+ [2]Op{OpAMD64SUBSSload, OpAMD64LEAQ4}: OpAMD64SUBSSloadidx4,
+ [2]Op{OpAMD64SUBSDload, OpAMD64LEAQ1}: OpAMD64SUBSDloadidx1,
+ [2]Op{OpAMD64SUBSDload, OpAMD64LEAQ8}: OpAMD64SUBSDloadidx8,
+ [2]Op{OpAMD64MULSSload, OpAMD64LEAQ1}: OpAMD64MULSSloadidx1,
+ [2]Op{OpAMD64MULSSload, OpAMD64LEAQ4}: OpAMD64MULSSloadidx4,
+ [2]Op{OpAMD64MULSDload, OpAMD64LEAQ1}: OpAMD64MULSDloadidx1,
+ [2]Op{OpAMD64MULSDload, OpAMD64LEAQ8}: OpAMD64MULSDloadidx8,
+ [2]Op{OpAMD64DIVSSload, OpAMD64LEAQ1}: OpAMD64DIVSSloadidx1,
+ [2]Op{OpAMD64DIVSSload, OpAMD64LEAQ4}: OpAMD64DIVSSloadidx4,
+ [2]Op{OpAMD64DIVSDload, OpAMD64LEAQ1}: OpAMD64DIVSDloadidx1,
+ [2]Op{OpAMD64DIVSDload, OpAMD64LEAQ8}: OpAMD64DIVSDloadidx8,
+
// 386
[2]Op{Op386MOVBload, Op386ADDL}: Op386MOVBloadidx1,
[2]Op{Op386MOVWload, Op386ADDL}: Op386MOVWloadidx1,
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
index cd9cb515c02551fc43b8b6126562ea37bfe25fbb..a3b29049df667277d3b4b8cf1ce5a3d9cf187839 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
@@ -149,14 +149,15 @@ gpstoreconstidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
gpstorexchg = regInfo{inputs: []regMask{gp, gpspsb, 0}, outputs: []regMask{gp}}
cmpxchg = regInfo{inputs: []regMask{gp, ax, gp, 0}, outputs: []regMask{gp, 0}, clobbers: ax}
- fp01 = regInfo{inputs: nil, outputs: fponly}
- fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
- fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: fponly}
- fp21load = regInfo{inputs: []regMask{fp, gpspsb, 0}, outputs: fponly}
- fpgp = regInfo{inputs: fponly, outputs: gponly}
- gpfp = regInfo{inputs: gponly, outputs: fponly}
- fp11 = regInfo{inputs: fponly, outputs: fponly}
- fp2flags = regInfo{inputs: []regMask{fp, fp}}
+ fp01 = regInfo{inputs: nil, outputs: fponly}
+ fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
+ fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: fponly}
+ fp21load = regInfo{inputs: []regMask{fp, gpspsb, 0}, outputs: fponly}
+ fp21loadidx = regInfo{inputs: []regMask{fp, gpspsb, gpspsb, 0}, outputs: fponly}
+ fpgp = regInfo{inputs: fponly, outputs: gponly}
+ gpfp = regInfo{inputs: gponly, outputs: fponly}
+ fp11 = regInfo{inputs: fponly, outputs: fponly}
+ fp2flags = regInfo{inputs: []regMask{fp, fp}}
fpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: fponly}
fploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: fponly}
@@ -200,6 +201,23 @@ {name: "MULSSload", argLength: 3, reg: fp21load, asm: "MULSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 * tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
{name: "MULSDload", argLength: 3, reg: fp21load, asm: "MULSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 * tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
{name: "DIVSSload", argLength: 3, reg: fp21load, asm: "DIVSS", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp32 arg0 / tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
{name: "DIVSDload", argLength: 3, reg: fp21load, asm: "DIVSD", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, symEffect: "Read"}, // fp64 arg0 / tmp, tmp loaded from arg1+auxint+aux, arg2 = mem
+
+ {name: "ADDSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "ADDSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 + tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "ADDSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "ADDSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 + tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "ADDSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "ADDSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 + tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "ADDSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "ADDSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 + tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "SUBSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "SUBSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 - tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "SUBSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "SUBSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 - tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "SUBSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "SUBSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 - tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "SUBSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "SUBSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 - tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "MULSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "MULSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 * tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "MULSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "MULSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 * tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "MULSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "MULSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 * tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "MULSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "MULSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 * tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
+ {name: "DIVSSloadidx1", argLength: 4, reg: fp21loadidx, asm: "DIVSS", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 / tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "DIVSSloadidx4", argLength: 4, reg: fp21loadidx, asm: "DIVSS", scale: 4, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp32 arg0 / tmp, tmp loaded from arg1+4*arg2+auxint+aux, arg3 = mem
+ {name: "DIVSDloadidx1", argLength: 4, reg: fp21loadidx, asm: "DIVSD", scale: 1, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 / tmp, tmp loaded from arg1+arg2+auxint+aux, arg3 = mem
+ {name: "DIVSDloadidx8", argLength: 4, reg: fp21loadidx, asm: "DIVSD", scale: 8, aux: "SymOff", resultInArg0: true, symEffect: "Read"}, // fp64 arg0 / tmp, tmp loaded from arg1+8*arg2+auxint+aux, arg3 = mem
// binary ops
{name: "ADDQ", argLength: 2, reg: gp21sp, asm: "ADDQ", commutative: true, clobberFlags: true}, // arg0 + arg1
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index d27682e3b38d922ae876a45081b9c840d99b7193..9efa1bfcc4bdc4bc8dd922433f80d44421763aac 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -572,6 +572,22 @@ OpAMD64MULSSload
OpAMD64MULSDload
OpAMD64DIVSSload
OpAMD64DIVSDload
+ OpAMD64ADDSSloadidx1
+ OpAMD64ADDSSloadidx4
+ OpAMD64ADDSDloadidx1
+ OpAMD64ADDSDloadidx8
+ OpAMD64SUBSSloadidx1
+ OpAMD64SUBSSloadidx4
+ OpAMD64SUBSDloadidx1
+ OpAMD64SUBSDloadidx8
+ OpAMD64MULSSloadidx1
+ OpAMD64MULSSloadidx4
+ OpAMD64MULSDloadidx1
+ OpAMD64MULSDloadidx8
+ OpAMD64DIVSSloadidx1
+ OpAMD64DIVSSloadidx4
+ OpAMD64DIVSDloadidx1
+ OpAMD64DIVSDloadidx8
OpAMD64ADDQ
OpAMD64ADDL
OpAMD64ADDQconst
@@ -6570,6 +6586,310 @@ reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
{1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "ADDSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AADDSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "SUBSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ASUBSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "MULSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.AMULSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSSloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSS,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSSloadidx4",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSS,
+ scale: 4,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSDloadidx1",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSD,
+ scale: 1,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ outputs: []outputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ },
+ },
+ },
+ {
+ name: "DIVSDloadidx8",
+ auxType: auxSymOff,
+ argLen: 4,
+ resultInArg0: true,
+ symEffect: SymRead,
+ asm: x86.ADIVSD,
+ scale: 8,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+ {1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ {2, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
},
outputs: []outputInfo{
{0, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go
index a8e43d01147110fd1eaec53c80cfc8d63351a4bf..6c6be39d34b60376e71874c3e2c2b016b18c01b9 100644
--- a/src/cmd/compile/internal/ssa/prove.go
+++ b/src/cmd/compile/internal/ssa/prove.go
@@ -1051,6 +1051,11 @@ // 4. min < max
//
// If all of these conditions are true, then i1 < max and i1 >= min.
+ // To ensure this is a loop header node.
+ if len(b.Preds) != 2 {
+ return
+ }
+
for _, i1 := range b.Values {
if i1.Op != OpPhi {
continue
@@ -1092,6 +1097,9 @@ if br != unknown {
continue
}
br = negative
+ }
+ if br == unknown {
+ continue
}
tr, has := domainRelationTable[control.Op]
diff --git a/src/cmd/go.mod b/src/cmd/go.mod
index 274ef0d9f084f1ab71ba37aaf08b913291e751ab..6d57ceee791698826cc0dd243f90149ffbc0098a 100644
--- a/src/cmd/go.mod
+++ b/src/cmd/go.mod
@@ -10,4 +10,5 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/mod v0.3.0
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054
+ golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316 // indirect
)
diff --git a/src/cmd/go.sum b/src/cmd/go.sum
index 30a0be03e47563cbbcf9ed9c1886874e2111d6b4..3fc693e3bfbd8dbc3f99018c7862bb6a32c51d00 100644
--- a/src/cmd/go.sum
+++ b/src/cmd/go.sum
@@ -34,4 +34,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316 h1:Jhw4VC65LaKnpq9FvcK+a8ZzrFm3D+UygvMMrhkOw70=
+golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index fcc47bd9c519836f5a6cedb7d6ed43b2c69781fe..2b5fbb1c5bd98b37f13aee19fd245eb1fef92a33 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -239,11 +239,25 @@ }
err = &NoGoError{Package: p}
}
+ // Take only the first error from a scanner.ErrorList. PackageError only
+ // has room for one position, so we report the first error with a position
+ // instead of all of the errors without a position.
+ var pos string
+ var isScanErr bool
+ if scanErr, ok := err.(scanner.ErrorList); ok && len(scanErr) > 0 {
+ isScanErr = true // For stack push/pop below.
+
+ scanPos := scanErr[0].Pos
+ scanPos.Filename = base.ShortPath(scanPos.Filename)
+ pos = scanPos.String()
+ err = errors.New(scanErr[0].Msg)
+ }
+
// Report the error on the importing package if the problem is with the import declaration
// for example, if the package doesn't exist or if the import path is malformed.
// On the other hand, don't include a position if the problem is with the imported package,
// for example there are no Go files (NoGoError), or there's a problem in the imported
- // package's source files themselves.
+ // package's source files themselves (scanner errors).
//
// TODO(matloob): Perhaps make each of those the errors in the first group
// (including modload.ImportMissingError, and the corresponding
@@ -254,20 +268,9 @@ // produced in golang.org/x/mod/module.CheckMod) implement an interface
// to make it easier to check for them? That would save us from having to
// move the modload errors into this package to avoid a package import cycle,
// and from having to export an error type for the errors produced in build.
- if !isMatchErr && nogoErr != nil {
+ if !isMatchErr && (nogoErr != nil || isScanErr) {
stk.Push(path)
defer stk.Pop()
- }
-
- // Take only the first error from a scanner.ErrorList. PackageError only
- // has room for one position, so we report the first error with a position
- // instead of all of the errors without a position.
- var pos string
- if scanErr, ok := err.(scanner.ErrorList); ok && len(scanErr) > 0 {
- scanPos := scanErr[0].Pos
- scanPos.Filename = base.ShortPath(scanPos.Filename)
- pos = scanPos.String()
- err = errors.New(scanErr[0].Msg)
}
p.Error = &PackageError{
diff --git a/src/cmd/go/testdata/script/list_err_stack.txt b/src/cmd/go/testdata/script/list_err_stack.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a7be9fde6d7b9336d9e409be976878c62a11031c
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_err_stack.txt
@@ -0,0 +1,27 @@
+
+# golang.org/issue/40544: regression in error stacks for parse errors
+
+env GO111MODULE=off
+cd sandbox/foo
+go list -e -json .
+stdout '"sandbox/foo"'
+stdout '"sandbox/bar"'
+stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
+stdout '"Err": "expected ''package'', found ackage"'
+
+env GO111MODULE=on
+go list -e -json .
+stdout '"sandbox/foo"'
+stdout '"sandbox/bar"'
+stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
+stdout '"Err": "expected ''package'', found ackage"'
+
+-- sandbox/go.mod --
+module sandbox
+
+-- sandbox/foo/foo.go --
+package pkg
+
+import "sandbox/bar"
+-- sandbox/bar/bar.go --
+ackage bar
\ No newline at end of file
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index b0a9613e4f478fda55a44b3c5dad81432a30ae33..0366bc7a6f456aa13b49481376091935ab55301a 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -2191,17 +2191,6 @@ su.SetType(sym.SDYNIMPORT)
l.SetSymElfType(s, elf.ST_TYPE(elfsym.Info))
su.SetSize(int64(elfsym.Size))
if elfsym.Section != elf.SHN_UNDEF {
- // If it's not undefined, mark the symbol as reachable
- // so as to protect it from dead code elimination,
- // even if there aren't any explicit references to it.
- // Under the previous sym.Symbol based regime this
- // wasn't necessary, but for the loader-based deadcode
- // it is definitely needed.
- //
- // FIXME: have a more general/flexible mechanism for this?
- //
- l.SetAttrReachable(s, true)
-
// Set .File for the library that actually defines the symbol.
l.SetSymPkg(s, libpath)
diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt
index 7ee7478b19a5230d7f68bc4612d17ed88660631a..21fc78c2375d5865847e941c9bde2967cb79de08 100644
--- a/src/cmd/vendor/modules.txt
+++ b/src/cmd/vendor/modules.txt
@@ -84,6 +84,7 @@ golang.org/x/tools/go/cfg
golang.org/x/tools/go/types/objectpath
golang.org/x/tools/go/types/typeutil
golang.org/x/tools/internal/analysisinternal
-# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
+# golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316
+## explicit
golang.org/x/xerrors
golang.org/x/xerrors/internal
diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go
index 5766970f82749ddd1202c258b81061862c253c9c..6f59bb5cffbe9d2632cb96549cfe7903789a10fb 100644
--- a/src/crypto/ed25519/ed25519.go
+++ b/src/crypto/ed25519/ed25519.go
@@ -154,7 +154,7 @@ sign(signature, privateKey, message)
return signature
}
-func signGeneric(signature, privateKey, message []byte) {
+func sign(signature, privateKey, message []byte) {
if l := len(privateKey); l != PrivateKeySize {
panic("ed25519: bad private key length: " + strconv.Itoa(l))
}
@@ -201,10 +201,6 @@
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
- return verify(publicKey, message, sig)
-}
-
-func verifyGeneric(publicKey PublicKey, message, sig []byte) bool {
if l := len(publicKey); l != PublicKeySize {
panic("ed25519: bad public key length: " + strconv.Itoa(l))
}
diff --git a/src/crypto/ed25519/ed25519_noasm.go b/src/crypto/ed25519/ed25519_noasm.go
deleted file mode 100644
index caa84f74fbcb66c6ef085796cbc506dc2f3fa7ca..0000000000000000000000000000000000000000
--- a/src/crypto/ed25519/ed25519_noasm.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2020 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.
-
-// +build !s390x
-
-package ed25519
-
-func sign(signature, privateKey, message []byte) {
- signGeneric(signature, privateKey, message)
-}
-
-func verify(publicKey PublicKey, message, sig []byte) bool {
- return verifyGeneric(publicKey, message, sig)
-}
diff --git a/src/crypto/ed25519/ed25519_s390x.go b/src/crypto/ed25519/ed25519_s390x.go
deleted file mode 100644
index c8627a065239248531ae52323a75bc4459d12941..0000000000000000000000000000000000000000
--- a/src/crypto/ed25519/ed25519_s390x.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2020 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 ed25519
-
-import (
- "internal/cpu"
- "strconv"
-)
-
-//go:noescape
-func kdsaSign(message, signature, privateKey []byte) bool
-
-//go:noescape
-func kdsaVerify(message, signature, publicKey []byte) bool
-
-// sign does a check to see if hardware has Edwards Curve instruction available.
-// If it does, use the hardware implementation. Otherwise, use the generic version.
-func sign(signature, privateKey, message []byte) {
- if cpu.S390X.HasEDDSA {
- if l := len(privateKey); l != PrivateKeySize {
- panic("ed25519: bad private key length: " + strconv.Itoa(l))
- }
-
- ret := kdsaSign(message, signature, privateKey[:32])
- if !ret {
- panic("ed25519: kdsa sign has a failure")
- }
- return
- }
- signGeneric(signature, privateKey, message)
-}
-
-// verify does a check to see if hardware has Edwards Curve instruction available.
-// If it does, use the hardware implementation for eddsa verfication. Otherwise, the generic
-// version is used
-func verify(publicKey PublicKey, message, sig []byte) bool {
- if cpu.S390X.HasEDDSA {
- if l := len(publicKey); l != PublicKeySize {
- panic("ed25519: bad public key length: " + strconv.Itoa(l))
- }
-
- if len(sig) != SignatureSize || sig[63]&224 != 0 {
- return false
- }
-
- return kdsaVerify(message, sig, publicKey)
- }
- return verifyGeneric(publicKey, message, sig)
-}
diff --git a/src/crypto/ed25519/ed25519_s390x.s b/src/crypto/ed25519/ed25519_s390x.s
deleted file mode 100644
index 1c77b51a7800be494f541ef9cbe74dfaa512a1a9..0000000000000000000000000000000000000000
--- a/src/crypto/ed25519/ed25519_s390x.s
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2020 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"
-
-// func kdsaSign(message, signature, privateKey []byte) bool
-TEXT ·kdsaSign(SB), $4096-73
- // The kdsa instruction takes function code,
- // buffer's location, message's location and message len
- // as parameters. Out of those, the function code and buffer's location
- // should be placed in R0 and R1 respectively. The message's location
- // and message length should be placed in an even-odd register pair. (e.g: R2 and R3)
-
- // The content of parameter block(buffer) looks like the following:
- // Signature R, Signature S and Private Key all take 32 bytes.
- // In the signing case, the signatures(R and S) will be generated by
- // the signing instruction and get placed in the locations shown in the parameter block.
- // 0 +---------------+
- // | Signature(R) |
- // 32 +---------------+
- // | Signature(S) |
- // 64 +---------------+
- // | Private Key |
- // 96 +---------------+
- // | Reserved |
- // 112+---------------+
- // | |
- // | ... |
- // | |
- // 4088 +---------------+
-
- // The following code section setups the buffer from stack:
- // Get the address of the buffer stack variable.
- MOVD $buffer-4096(SP), R1
-
- // Zero the buffer.
- MOVD R1, R2
- MOVD $(4096/256), R0 // number of 256 byte chunks to clear
-
-clear:
- XC $256, (R2), (R2)
- MOVD $256(R2), R2
- BRCTG R0, clear
-
- MOVD $40, R0 // EDDSA-25519 sign has a function code of 40
- LMG message+0(FP), R2, R3 // R2=base R3=len
- LMG signature+24(FP), R4, R5 // R4=base R5=len
- LMG privateKey+48(FP), R6, R7 // R6=base R7=len
-
- // Checks the length of signature and private key
- CMPBNE R5, $64, panic
- CMPBNE R7, $32, panic
-
- // The instruction uses RFC 8032's private key, which is the first 32 bytes
- // of the private key in this package. So we copy that into the buffer.
- MVC $32, (R6), 64(R1)
-
-loop:
- WORD $0xB93A0002 // The KDSA instruction
- BVS loop // The instruction is exectued by hardware and can be interrupted. This does a retry when that happens.
- BNE error
-
-success:
- // The signatures generated are in big-endian form, so we
- // need to reverse the bytes of Signature(R) and Signature(S) in the buffers to transform
- // them from big-endian to little-endian.
-
- // Transform Signature(R) from big endian to little endian and copy into the signature
- MVCIN $32, 31(R1), (R4)
-
- // Transform Signature(S) from big endian to little endian and copy into the signature
- MVCIN $32, 63(R1), 32(R4)
-
- MOVB $1, ret+72(FP)
- RET
-
-error:
- // return false
- MOVB $0, ret+72(FP)
- RET
-
-panic:
- UNDEF
-
-// func kdsaVerify(message, signature, publicKey []byte) bool
-TEXT ·kdsaVerify(SB), $4096-73
- // The kdsa instruction takes function code,
- // buffer's location, message's location and message len
- // as parameters. Out of those, the function code and buffer's location
- // should be placed in R0 and R1 respectively. The message's location
- // and message length should be placed in an even-odd register pair. (e.g: R2 and R3)
-
- // The parameter block(buffer) is similar to that of signing, except that
- // we use public key for verification, and Signatures(R and S) are provided
- // as input parameters to the parameter block.
- // 0 +---------------+
- // | Signature(R) |
- // 32 +---------------+
- // | Signature(S) |
- // 64 +---------------+
- // | Public Key |
- // 96 +---------------+
- // | Reserved |
- // 112+---------------+
- // | |
- // | ... |
- // | |
- // 4088 +---------------+
-
- // The following code section setups the buffer from stack:
- // Get the address of the buffer stack variable.
- MOVD $buffer-4096(SP), R1
-
- // Zero the buffer.
- MOVD R1, R2
- MOVD $(4096/256), R0 // number of 256 byte chunks to clear
-
-clear:
- XC $256, (R2), (R2)
- MOVD $256(R2), R2
- BRCTG R0, clear
-
- MOVD $32, R0 // EDDSA-25519 verify has a function code of 32
- LMG message+0(FP), R2, R3 // R2=base R3=len
- LMG signature+24(FP), R4, R5 // R4=base R5=len
- LMG publicKey+48(FP), R6, R7 // R6=base R7=len
-
- // Checks the length of public key and signature
- CMPBNE R5, $64, panic
- CMPBNE R7, $32, panic
-
-verify:
- // The instruction needs Signature(R), Signature(S) and public key
- // to be in big-endian form during computation. Therefore,
- // we do the transformation (from little endian to big endian) and copy those into the buffer.
-
- // Transform Signature(R) from little endian to big endian and copy into the buffer
- MVCIN $32, 31(R4), (R1)
-
- // Transform Signature(S) from little endian to big endian and copy into the buffer
- MVCIN $32, 63(R4), 32(R1)
-
- // Transform Public Key from little endian to big endian and copy into the buffer
- MVCIN $32, 31(R6), 64(R1)
-
-verifyLoop:
- WORD $0xB93A0002 // KDSA instruction
- BVS verifyLoop // Retry upon hardware interrupt
- BNE error
-
-success:
- MOVB $1, ret+72(FP)
- RET
-
-error:
- MOVB $0, ret+72(FP)
- RET
-
-panic:
- UNDEF
diff --git a/src/crypto/ed25519/ed25519_test.go b/src/crypto/ed25519/ed25519_test.go
index f77d463721c475688c11d45a94f448f5c1761feb..adb09e409a502c58a4f7910c4308a18708e5f9cc 100644
--- a/src/crypto/ed25519/ed25519_test.go
+++ b/src/crypto/ed25519/ed25519_test.go
@@ -26,14 +26,6 @@ }
return len(buf), nil
}
-// signGenericWrapper is identical to Sign except that it unconditionally calls signGeneric directly
-// rather than going through the sign function that might call assembly code.
-func signGenericWrapper(privateKey PrivateKey, msg []byte) []byte {
- sig := make([]byte, SignatureSize)
- signGeneric(sig, privateKey, msg)
- return sig
-}
-
func TestUnmarshalMarshal(t *testing.T) {
pub, _, _ := GenerateKey(rand.Reader)
@@ -53,33 +45,22 @@ }
}
func TestSignVerify(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testSignVerify(t, signGenericWrapper, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testSignVerify(t, Sign, Verify) })
-}
-
-func testSignVerify(t *testing.T, signImpl func(privateKey PrivateKey, message []byte) []byte,
- verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
var zero zeroReader
public, private, _ := GenerateKey(zero)
message := []byte("test message")
- sig := signImpl(private, message)
- if !verifyImpl(public, message, sig) {
+ sig := Sign(private, message)
+ if !Verify(public, message, sig) {
t.Errorf("valid signature rejected")
}
wrongMessage := []byte("wrong message")
- if verifyImpl(public, wrongMessage, sig) {
+ if Verify(public, wrongMessage, sig) {
t.Errorf("signature of different message accepted")
}
}
func TestCryptoSigner(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testCryptoSigner(t, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testCryptoSigner(t, Verify) })
-}
-
-func testCryptoSigner(t *testing.T, verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
var zero zeroReader
public, private, _ := GenerateKey(zero)
@@ -102,7 +83,7 @@ if err != nil {
t.Fatalf("error from Sign(): %s", err)
}
- if !verifyImpl(public, message, signature) {
+ if !Verify(public, message, signature) {
t.Errorf("Verify failed on signature from Sign()")
}
}
@@ -130,12 +111,6 @@ }
}
func TestGolden(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testGolden(t, signGenericWrapper, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testGolden(t, Sign, Verify) })
-}
-
-func testGolden(t *testing.T, signImpl func(privateKey PrivateKey, message []byte) []byte,
- verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
// sign.input.gz is a selection of test cases from
// https://ed25519.cr.yp.to/python/sign.input
testDataZ, err := os.Open("testdata/sign.input.gz")
@@ -177,12 +152,12 @@ var priv [PrivateKeySize]byte
copy(priv[:], privBytes)
copy(priv[32:], pubKey)
- sig2 := signImpl(priv[:], msg)
+ sig2 := Sign(priv[:], msg)
if !bytes.Equal(sig, sig2[:]) {
t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
}
- if !verifyImpl(pubKey, msg, sig2) {
+ if !Verify(pubKey, msg, sig2) {
t.Errorf("signature failed to verify on line %d", lineNo)
}
@@ -206,11 +181,6 @@ }
}
func TestMalleability(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testMalleability(t, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testMalleability(t, Verify) })
-}
-
-func testMalleability(t *testing.T, verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
// that s be in [0, order). This prevents someone from adding a multiple of
// order to s and obtaining a second valid signature for the same message.
@@ -229,7 +199,7 @@ 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
}
- if verifyImpl(publicKey, msg, sig) {
+ if Verify(publicKey, msg, sig) {
t.Fatal("non-canonical signature accepted")
}
}
diff --git a/src/encoding/binary/varint.go b/src/encoding/binary/varint.go
index bcb8ac9a459c5c20ceefe3e9ad9f69e5177b9c83..38af61075c860ef6b97b883bc6be2508a1c914f1 100644
--- a/src/encoding/binary/varint.go
+++ b/src/encoding/binary/varint.go
@@ -106,13 +106,13 @@ // ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
func ReadUvarint(r io.ByteReader) (uint64, error) {
var x uint64
var s uint
- for i := 0; ; i++ {
+ for i := 0; i < MaxVarintLen64; i++ {
b, err := r.ReadByte()
if err != nil {
return x, err
}
if b < 0x80 {
- if i > 9 || i == 9 && b > 1 {
+ if i == 9 && b > 1 {
return x, overflow
}
return x | uint64(b)< MaxVarintLen64 {
+ t.Errorf("ReadUvarint(%v): read more than MaxVarintLen64 bytes, got %d", buf, read)
}
}
func TestOverflow(t *testing.T) {
- testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, -10, overflow)
- testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, -13, overflow)
+ testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, 0, -10, overflow)
+ testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -13, overflow)
+ testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, 0, overflow) // 11 bytes, should overflow
}
func TestNonCanonicalZero(t *testing.T) {
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index a41e732d983da433c1c7c103d06e115eb8b3fc0a..d37b52b13d06006619d341692680bf13cc1a4d52 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -100,7 +100,7 @@ idleConnWait map[connectMethodKey]wantConnQueue // waiting getConns
idleLRU connLRU
reqMu sync.Mutex
- reqCanceler map[*Request]func(error)
+ reqCanceler map[cancelKey]func(error)
altMu sync.Mutex // guards changing altProto only
altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme
@@ -273,6 +273,13 @@ // upgrades, set this to true.
ForceAttemptHTTP2 bool
}
+// A cancelKey is the key of the reqCanceler map.
+// We wrap the *Request in this type since we want to use the original request,
+// not any transient one created by roundTrip.
+type cancelKey struct {
+ req *Request
+}
+
func (t *Transport) writeBufferSize() int {
if t.WriteBufferSize > 0 {
return t.WriteBufferSize
@@ -433,9 +440,10 @@ // transportRequest is a wrapper around a *Request that adds
// optional extra headers to write and stores any error to return
// from roundTrip.
type transportRequest struct {
- *Request // original request, not to be mutated
- extra Header // extra headers to write, or nil
- trace *httptrace.ClientTrace // optional
+ *Request // original request, not to be mutated
+ extra Header // extra headers to write, or nil
+ trace *httptrace.ClientTrace // optional
+ cancelKey cancelKey
mu sync.Mutex // guards err
err error // first setError value for mapRoundTripError to consider
@@ -512,6 +520,7 @@ }
}
origReq := req
+ cancelKey := cancelKey{origReq}
req = setupRewindBody(req)
if altRT := t.alternateRoundTripper(req); altRT != nil {
@@ -546,7 +555,7 @@ default:
}
// treq gets modified by roundTrip, so we need to recreate for each retry.
- treq := &transportRequest{Request: req, trace: trace}
+ treq := &transportRequest{Request: req, trace: trace, cancelKey: cancelKey}
cm, err := t.connectMethodForRequest(treq)
if err != nil {
req.closeBody()
@@ -559,7 +568,7 @@ // pre-CONNECTed to https server. In any case, we'll be ready
// to send it requests.
pconn, err := t.getConn(treq, cm)
if err != nil {
- t.setReqCanceler(req, nil)
+ t.setReqCanceler(cancelKey, nil)
req.closeBody()
return nil, err
}
@@ -567,7 +576,7 @@
var resp *Response
if pconn.alt != nil {
// HTTP/2 path.
- t.setReqCanceler(req, nil) // not cancelable with CancelRequest
+ t.setReqCanceler(cancelKey, nil) // not cancelable with CancelRequest
resp, err = pconn.alt.RoundTrip(req)
} else {
resp, err = pconn.roundTrip(treq)
@@ -753,14 +762,14 @@ // Deprecated: Use Request.WithContext to create a request with a
// cancelable context instead. CancelRequest cannot cancel HTTP/2
// requests.
func (t *Transport) CancelRequest(req *Request) {
- t.cancelRequest(req, errRequestCanceled)
+ t.cancelRequest(cancelKey{req}, errRequestCanceled)
}
// Cancel an in-flight request, recording the error value.
-func (t *Transport) cancelRequest(req *Request, err error) {
+func (t *Transport) cancelRequest(key cancelKey, err error) {
t.reqMu.Lock()
- cancel := t.reqCanceler[req]
- delete(t.reqCanceler, req)
+ cancel := t.reqCanceler[key]
+ delete(t.reqCanceler, key)
t.reqMu.Unlock()
if cancel != nil {
cancel(err)
@@ -1093,16 +1102,16 @@ }
return removed
}
-func (t *Transport) setReqCanceler(r *Request, fn func(error)) {
+func (t *Transport) setReqCanceler(key cancelKey, fn func(error)) {
t.reqMu.Lock()
defer t.reqMu.Unlock()
if t.reqCanceler == nil {
- t.reqCanceler = make(map[*Request]func(error))
+ t.reqCanceler = make(map[cancelKey]func(error))
}
if fn != nil {
- t.reqCanceler[r] = fn
+ t.reqCanceler[key] = fn
} else {
- delete(t.reqCanceler, r)
+ delete(t.reqCanceler, key)
}
}
@@ -1110,17 +1119,17 @@ // replaceReqCanceler replaces an existing cancel function. If there is no cancel function
// for the request, we don't set the function and return false.
// Since CancelRequest will clear the canceler, we can use the return value to detect if
// the request was canceled since the last setReqCancel call.
-func (t *Transport) replaceReqCanceler(r *Request, fn func(error)) bool {
+func (t *Transport) replaceReqCanceler(key cancelKey, fn func(error)) bool {
t.reqMu.Lock()
defer t.reqMu.Unlock()
- _, ok := t.reqCanceler[r]
+ _, ok := t.reqCanceler[key]
if !ok {
return false
}
if fn != nil {
- t.reqCanceler[r] = fn
+ t.reqCanceler[key] = fn
} else {
- delete(t.reqCanceler, r)
+ delete(t.reqCanceler, key)
}
return true
}
@@ -1324,12 +1333,12 @@ }
// set request canceler to some non-nil function so we
// can detect whether it was cleared between now and when
// we enter roundTrip
- t.setReqCanceler(req, func(error) {})
+ t.setReqCanceler(treq.cancelKey, func(error) {})
return pc, nil
}
cancelc := make(chan error, 1)
- t.setReqCanceler(req, func(err error) { cancelc <- err })
+ t.setReqCanceler(treq.cancelKey, func(err error) { cancelc <- err })
// Queue for permission to dial.
t.queueForDial(w)
@@ -2078,7 +2087,7 @@ alive = false
}
if !hasBody || bodyWritable {
- pc.t.setReqCanceler(rc.req, nil)
+ pc.t.setReqCanceler(rc.cancelKey, nil)
// Put the idle conn back into the pool before we send the response
// so if they process it quickly and make another request, they'll
@@ -2151,7 +2160,7 @@ // the bufio.Reader, wait for the caller goroutine to finish
// reading the response body. (or for cancellation or death)
select {
case bodyEOF := <-waitForBodyRead:
- pc.t.setReqCanceler(rc.req, nil) // before pc might return to idle pool
+ pc.t.setReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool
alive = alive &&
bodyEOF &&
!pc.sawEOF &&
@@ -2165,7 +2174,7 @@ alive = false
pc.t.CancelRequest(rc.req)
case <-rc.req.Context().Done():
alive = false
- pc.t.cancelRequest(rc.req, rc.req.Context().Err())
+ pc.t.cancelRequest(rc.cancelKey, rc.req.Context().Err())
case <-pc.closech:
alive = false
}
@@ -2408,9 +2417,10 @@ err error
}
type requestAndChan struct {
- _ incomparable
- req *Request
- ch chan responseAndError // unbuffered; always send in select on callerGone
+ _ incomparable
+ req *Request
+ cancelKey cancelKey
+ ch chan responseAndError // unbuffered; always send in select on callerGone
// whether the Transport (as opposed to the user client code)
// added the Accept-Encoding gzip header. If the Transport
@@ -2472,7 +2482,7 @@ )
func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
testHookEnterRoundTrip()
- if !pc.t.replaceReqCanceler(req.Request, pc.cancelRequest) {
+ if !pc.t.replaceReqCanceler(req.cancelKey, pc.cancelRequest) {
pc.t.putOrCloseIdleConn(pc)
return nil, errRequestCanceled
}
@@ -2524,7 +2534,7 @@ defer close(gone)
defer func() {
if err != nil {
- pc.t.setReqCanceler(req.Request, nil)
+ pc.t.setReqCanceler(req.cancelKey, nil)
}
}()
@@ -2540,6 +2550,7 @@
resc := make(chan responseAndError)
pc.reqch <- requestAndChan{
req: req.Request,
+ cancelKey: req.cancelKey,
ch: resc,
addedGzip: requestedGzip,
continueCh: continueCh,
@@ -2591,10 +2602,10 @@ return nil, pc.mapRoundTripError(req, startBytesWritten, re.err)
}
return re.res, nil
case <-cancelChan:
- pc.t.CancelRequest(req.Request)
+ pc.t.cancelRequest(req.cancelKey, errRequestCanceled)
cancelChan = nil
case <-ctxDoneChan:
- pc.t.cancelRequest(req.Request, req.Context().Err())
+ pc.t.cancelRequest(req.cancelKey, req.Context().Err())
cancelChan = nil
ctxDoneChan = nil
}
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 31a41f535115236817110fcd0bf6374cddcb3772..0a47687d9afbacac2ac7411c2e91e41b8b0915a9 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -2364,6 +2364,50 @@ }
}
}
+func testTransportCancelRequestInDo(t *testing.T, body io.Reader) {
+ setParallel(t)
+ defer afterTest(t)
+ if testing.Short() {
+ t.Skip("skipping test in -short mode")
+ }
+ unblockc := make(chan bool)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ <-unblockc
+ }))
+ defer ts.Close()
+ defer close(unblockc)
+
+ c := ts.Client()
+ tr := c.Transport.(*Transport)
+
+ donec := make(chan bool)
+ req, _ := NewRequest("GET", ts.URL, body)
+ go func() {
+ defer close(donec)
+ c.Do(req)
+ }()
+ start := time.Now()
+ timeout := 10 * time.Second
+ for time.Since(start) < timeout {
+ time.Sleep(100 * time.Millisecond)
+ tr.CancelRequest(req)
+ select {
+ case <-donec:
+ return
+ default:
+ }
+ }
+ t.Errorf("Do of canceled request has not returned after %v", timeout)
+}
+
+func TestTransportCancelRequestInDo(t *testing.T) {
+ testTransportCancelRequestInDo(t, nil)
+}
+
+func TestTransportCancelRequestWithBodyInDo(t *testing.T) {
+ testTransportCancelRequestInDo(t, bytes.NewBuffer([]byte{0}))
+}
+
func TestTransportCancelRequestInDial(t *testing.T) {
defer afterTest(t)
if testing.Short() {
diff --git a/src/runtime/lockrank_off.go b/src/runtime/lockrank_off.go
index 891589c0f27772d9d8f3d974a1f5ac92293c25ba..425ca8dd93f680ac7fc9c9b57c64d06fc0a7cd93 100644
--- a/src/runtime/lockrank_off.go
+++ b/src/runtime/lockrank_off.go
@@ -1,3 +1,7 @@
+// Copyright 2020 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.
+
// +build !goexperiment.staticlockranking
package runtime
diff --git a/src/runtime/lockrank_on.go b/src/runtime/lockrank_on.go
index cf4151ff4622aa01a6c7d62b6062d15aedc8483c..fbc5ff58b72e6709ad67385ffc0ecdfab114ea20 100644
--- a/src/runtime/lockrank_on.go
+++ b/src/runtime/lockrank_on.go
@@ -1,3 +1,7 @@
+// Copyright 2020 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.
+
// +build goexperiment.staticlockranking
package runtime
diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go
index 60f7f9ff58e7bd8fd2e2897118fc8e62406890cd..8b3c62c375e76f2efbd1f08a566af86b86954eaf 100644
--- a/src/runtime/mpagealloc.go
+++ b/src/runtime/mpagealloc.go
@@ -233,16 +233,12 @@ chunks [1 << pallocChunksL1Bits]*[1 << pallocChunksL2Bits]pallocData
// The address to start an allocation search with. It must never
// point to any memory that is not contained in inUse, i.e.
- // inUse.contains(searchAddr) must always be true.
- //
- // When added with arenaBaseOffset, we guarantee that
- // all valid heap addresses (when also added with
- // arenaBaseOffset) below this value are allocated and
- // not worth searching.
+ // inUse.contains(searchAddr.addr()) must always be true. The one
+ // exception to this rule is that it may take on the value of
+ // maxOffAddr to indicate that the heap is exhausted.
//
- // Note that adding in arenaBaseOffset transforms addresses
- // to a new address space with a linear view of the full address
- // space on architectures with segmented address spaces.
+ // We guarantee that all valid heap addresses below this value
+ // are allocated and not worth searching.
searchAddr offAddr
// start and end represent the chunk indices
@@ -518,6 +514,30 @@ s.update(base, npages, true, true)
return uintptr(scav) * pageSize
}
+// findMappedAddr returns the smallest mapped offAddr that is
+// >= addr. That is, if addr refers to mapped memory, then it is
+// returned. If addr is higher than any mapped region, then
+// it returns maxOffAddr.
+//
+// s.mheapLock must be held.
+func (s *pageAlloc) findMappedAddr(addr offAddr) offAddr {
+ // If we're not in a test, validate first by checking mheap_.arenas.
+ // This is a fast path which is only safe to use outside of testing.
+ ai := arenaIndex(addr.addr())
+ if s.test || mheap_.arenas[ai.l1()] == nil || mheap_.arenas[ai.l1()][ai.l2()] == nil {
+ vAddr, ok := s.inUse.findAddrGreaterEqual(addr.addr())
+ if ok {
+ return offAddr{vAddr}
+ } else {
+ // The candidate search address is greater than any
+ // known address, which means we definitely have no
+ // free memory left.
+ return maxOffAddr
+ }
+ }
+ return addr
+}
+
// find searches for the first (address-ordered) contiguous free region of
// npages in size and returns a base address for that region.
//
@@ -526,6 +546,7 @@ // below chunkIndex(s.searchAddr) contain any free memory at all.
//
// find also computes and returns a candidate s.searchAddr, which may or
// may not prune more of the address space than s.searchAddr already does.
+// This candidate is always a valid s.searchAddr.
//
// find represents the slow path and the full radix tree search.
//
@@ -695,7 +716,7 @@ if size >= uint(npages) {
// We found a sufficiently large run of free pages straddling
// some boundary, so compute the address and return it.
addr := levelIndexToOffAddr(l, i).add(uintptr(base) * pageSize).addr()
- return addr, firstFree.base
+ return addr, s.findMappedAddr(firstFree.base)
}
if l == 0 {
// We're at level zero, so that means we've exhausted our search.
@@ -741,7 +762,7 @@ // Since we actually searched the chunk, we may have
// found an even narrower free window.
searchAddr := chunkBase(ci) + uintptr(searchIdx)*pageSize
foundFree(offAddr{searchAddr}, chunkBase(ci+1)-searchAddr)
- return addr, firstFree.base
+ return addr, s.findMappedAddr(firstFree.base)
}
// alloc allocates npages worth of memory from the page heap, returning the base
diff --git a/src/runtime/mpagealloc_test.go b/src/runtime/mpagealloc_test.go
index 89a4a2502cec6e3fe71d7f1ff89be4d583e03f73..65ba71d459ce60248979508b19b8b3dc79e25bab 100644
--- a/src/runtime/mpagealloc_test.go
+++ b/src/runtime/mpagealloc_test.go
@@ -612,6 +612,63 @@ baseChunkIdx + sumsPerPhysPage - 1: {{0, PallocChunkPages}},
baseChunkIdx + chunkIdxBigJump: {{0, PallocChunkPages}},
},
}
+
+ // Test to check for issue #40191. Essentially, the candidate searchAddr
+ // discovered by find may not point to mapped memory, so we need to handle
+ // that explicitly.
+ //
+ // chunkIdxSmallOffset is an offset intended to be used within chunkIdxBigJump.
+ // It is far enough within chunkIdxBigJump that the summaries at the beginning
+ // of an address range the size of chunkIdxBigJump will not be mapped in.
+ const chunkIdxSmallOffset = 0x503
+ tests["DiscontiguousBadSearchAddr"] = test{
+ before: map[ChunkIdx][]BitRange{
+ // The mechanism for the bug involves three chunks, A, B, and C, which are
+ // far apart in the address space. In particular, B is chunkIdxBigJump +
+ // chunkIdxSmalloffset chunks away from B, and C is 2*chunkIdxBigJump chunks
+ // away from A. A has 1 page free, B has several (NOT at the end of B), and
+ // C is totally free.
+ // Note that B's free memory must not be at the end of B because the fast
+ // path in the page allocator will check if the searchAddr even gives us
+ // enough space to place the allocation in a chunk before accessing the
+ // summary.
+ BaseChunkIdx + chunkIdxBigJump*0: {{0, PallocChunkPages - 1}},
+ BaseChunkIdx + chunkIdxBigJump*1 + chunkIdxSmallOffset: {
+ {0, PallocChunkPages - 10},
+ {PallocChunkPages - 1, 1},
+ },
+ BaseChunkIdx + chunkIdxBigJump*2: {},
+ },
+ scav: map[ChunkIdx][]BitRange{
+ BaseChunkIdx + chunkIdxBigJump*0: {},
+ BaseChunkIdx + chunkIdxBigJump*1 + chunkIdxSmallOffset: {},
+ BaseChunkIdx + chunkIdxBigJump*2: {},
+ },
+ hits: []hit{
+ // We first allocate into A to set the page allocator's searchAddr to the
+ // end of that chunk. That is the only purpose A serves.
+ {1, PageBase(BaseChunkIdx, PallocChunkPages-1), 0},
+ // Then, we make a big allocation that doesn't fit into B, and so must be
+ // fulfilled by C.
+ //
+ // On the way to fulfilling the allocation into C, we estimate searchAddr
+ // using the summary structure, but that will give us a searchAddr of
+ // B's base address minus chunkIdxSmallOffset chunks. These chunks will
+ // not be mapped.
+ {100, PageBase(baseChunkIdx+chunkIdxBigJump*2, 0), 0},
+ // Now we try to make a smaller allocation that can be fulfilled by B.
+ // In an older implementation of the page allocator, this will segfault,
+ // because this last allocation will first try to access the summary
+ // for B's base address minus chunkIdxSmallOffset chunks in the fast path,
+ // and this will not be mapped.
+ {9, PageBase(baseChunkIdx+chunkIdxBigJump*1+chunkIdxSmallOffset, PallocChunkPages-10), 0},
+ },
+ after: map[ChunkIdx][]BitRange{
+ BaseChunkIdx + chunkIdxBigJump*0: {{0, PallocChunkPages}},
+ BaseChunkIdx + chunkIdxBigJump*1 + chunkIdxSmallOffset: {{0, PallocChunkPages}},
+ BaseChunkIdx + chunkIdxBigJump*2: {{0, 100}},
+ },
+ }
}
for name, v := range tests {
v := v
diff --git a/src/runtime/mranges.go b/src/runtime/mranges.go
index e23d0778eb974a2f7d4fe018fef716a1aabf51b0..2c0eb2c2ddf5e4c68cd3bca5598e780e2493e54d 100644
--- a/src/runtime/mranges.go
+++ b/src/runtime/mranges.go
@@ -188,6 +188,25 @@ }
return len(a.ranges)
}
+// findAddrGreaterEqual returns the smallest address represented by a
+// that is >= addr. Thus, if the address is represented by a,
+// then it returns addr. The second return value indicates whether
+// such an address exists for addr in a. That is, if addr is larger than
+// any address known to a, the second return value will be false.
+func (a *addrRanges) findAddrGreaterEqual(addr uintptr) (uintptr, bool) {
+ i := a.findSucc(addr)
+ if i == 0 {
+ return a.ranges[0].base.addr(), true
+ }
+ if a.ranges[i-1].contains(addr) {
+ return addr, true
+ }
+ if i < len(a.ranges) {
+ return a.ranges[i].base.addr(), true
+ }
+ return 0, false
+}
+
// contains returns true if a covers the address addr.
func (a *addrRanges) contains(addr uintptr) bool {
i := a.findSucc(addr)
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 2399f0a1d3d0628b92022dec930effea21c4f993..035822216d2bb860e544f2a0f83d31674718075b 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -132,7 +132,7 @@ mainStarted = true
if GOARCH != "wasm" { // no threads on wasm yet, so no sysmon
systemstack(func() {
- newm(sysmon, nil)
+ newm(sysmon, nil, -1)
})
}
@@ -562,7 +562,7 @@ moduledataverify()
stackinit()
mallocinit()
fastrandinit() // must run before mcommoninit
- mcommoninit(_g_.m)
+ mcommoninit(_g_.m, -1)
cpuinit() // must run before alginit
alginit() // maps must not be used before this call
modulesinit() // provides activeModules
@@ -623,7 +623,22 @@ throw("thread exhaustion")
}
}
-func mcommoninit(mp *m) {
+// mReserveID returns the next ID to use for a new m. This new m is immediately
+// considered 'running' by checkdead.
+//
+// sched.lock must be held.
+func mReserveID() int64 {
+ if sched.mnext+1 < sched.mnext {
+ throw("runtime: thread ID overflow")
+ }
+ id := sched.mnext
+ sched.mnext++
+ checkmcount()
+ return id
+}
+
+// Pre-allocated ID may be passed as 'id', or omitted by passing -1.
+func mcommoninit(mp *m, id int64) {
_g_ := getg()
// g0 stack won't make sense for user (and is not necessary unwindable).
@@ -632,12 +647,12 @@ callers(1, mp.createstack[:])
}
lock(&sched.lock)
- if sched.mnext+1 < sched.mnext {
- throw("runtime: thread ID overflow")
+
+ if id >= 0 {
+ mp.id = id
+ } else {
+ mp.id = mReserveID()
}
- mp.id = sched.mnext
- sched.mnext++
- checkmcount()
mp.fastrand[0] = uint32(int64Hash(uint64(mp.id), fastrandseed))
mp.fastrand[1] = uint32(int64Hash(uint64(cputicks()), ^fastrandseed))
@@ -1068,7 +1083,7 @@ mp.nextp.set(p)
notewakeup(&mp.park)
} else {
// Start M to run P. Do not start another M below.
- newm(nil, p)
+ newm(nil, p, -1)
}
}
@@ -1413,12 +1428,13 @@
// Allocate a new m unassociated with any thread.
// Can use p for allocation context if needed.
// fn is recorded as the new m's m.mstartfn.
+// id is optional pre-allocated m ID. Omit by passing -1.
//
// This function is allowed to have write barriers even if the caller
// isn't because it borrows _p_.
//
//go:yeswritebarrierrec
-func allocm(_p_ *p, fn func()) *m {
+func allocm(_p_ *p, fn func(), id int64) *m {
_g_ := getg()
acquirem() // disable GC because it can be called from sysmon
if _g_.m.p == 0 {
@@ -1447,7 +1463,7 @@ }
mp := new(m)
mp.mstartfn = fn
- mcommoninit(mp)
+ mcommoninit(mp, id)
// In case of cgo or Solaris or illumos or Darwin, pthread_create will make us a stack.
// Windows and Plan 9 will layout sched stack on OS stack.
@@ -1586,7 +1602,7 @@ // The goroutine is the context in which the cgo callback will run.
// The sched.pc will never be returned to, but setting it to
// goexit makes clear to the traceback routines where
// the goroutine stack ends.
- mp := allocm(nil, nil)
+ mp := allocm(nil, nil, -1)
gp := malg(4096)
gp.sched.pc = funcPC(goexit) + sys.PCQuantum
gp.sched.sp = gp.stack.hi
@@ -1757,9 +1773,11 @@
// Create a new m. It will start off with a call to fn, or else the scheduler.
// fn needs to be static and not a heap allocated closure.
// May run with m.p==nil, so write barriers are not allowed.
+//
+// id is optional pre-allocated m ID. Omit by passing -1.
//go:nowritebarrierrec
-func newm(fn func(), _p_ *p) {
- mp := allocm(_p_, fn)
+func newm(fn func(), _p_ *p, id int64) {
+ mp := allocm(_p_, fn, id)
mp.nextp.set(_p_)
mp.sigmask = initSigmask
if gp := getg(); gp != nil && gp.m != nil && (gp.m.lockedExt != 0 || gp.m.incgo) && GOOS != "plan9" {
@@ -1828,7 +1846,7 @@ if !atomic.Cas(&newmHandoff.haveTemplateThread, 0, 1) {
releasem(mp)
return
}
- newm(templateThread, nil)
+ newm(templateThread, nil, -1)
releasem(mp)
}
@@ -1923,16 +1941,31 @@ return
}
}
mp := mget()
- unlock(&sched.lock)
if mp == nil {
+ // No M is available, we must drop sched.lock and call newm.
+ // However, we already own a P to assign to the M.
+ //
+ // Once sched.lock is released, another G (e.g., in a syscall),
+ // could find no idle P while checkdead finds a runnable G but
+ // no running M's because this new M hasn't started yet, thus
+ // throwing in an apparent deadlock.
+ //
+ // Avoid this situation by pre-allocating the ID for the new M,
+ // thus marking it as 'running' before we drop sched.lock. This
+ // new M will eventually run the scheduler to execute any
+ // queued G's.
+ id := mReserveID()
+ unlock(&sched.lock)
+
var fn func()
if spinning {
// The caller incremented nmspinning, so set m.spinning in the new M.
fn = mspinning
}
- newm(fn, _p_)
+ newm(fn, _p_, id)
return
}
+ unlock(&sched.lock)
if mp.spinning {
throw("startm: m is spinning")
}
@@ -5192,7 +5225,9 @@ }
atomic.StoreRel(&pp.runqtail, t)
if !q.empty() {
+ lock(&sched.lock)
globrunqputbatch(q, int32(qsize))
+ unlock(&sched.lock)
}
}
diff --git a/src/runtime/race/README b/src/runtime/race/README
index 65378c8ca66c37d30fd1828b104c9c8d6aea9ea3..34485f0fb2e0a08c7e162932b85ba98ca892ab1f 100644
--- a/src/runtime/race/README
+++ b/src/runtime/race/README
@@ -6,8 +6,8 @@ To update the .syso files use golang.org/x/build/cmd/racebuild.
race_darwin_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
race_freebsd_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
-race_linux_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
-race_linux_ppc64le.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
+race_linux_amd64.syso built with LLVM 6c75db8b4bc59eace18143ce086419d37da24746 and Go 7388956b76ce15a11346cebefcf6193db044caaf.
+race_linux_ppc64le.syso built with LLVM 6c75db8b4bc59eace18143ce086419d37da24746 and Go 7388956b76ce15a11346cebefcf6193db044caaf.
race_netbsd_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
race_windows_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
-race_linux_arm64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
+race_linux_arm64.syso built with LLVM 6c75db8b4bc59eace18143ce086419d37da24746 and Go 7388956b76ce15a11346cebefcf6193db044caaf.
diff --git a/src/runtime/race/race_linux_amd64.syso b/src/runtime/race/race_linux_amd64.syso
index 255b2e5c0853abcdaaca210cc7723aad84c5ea87..d31f85df56d8a86a5c124430b380bdbe6ae84158 100644
Binary files a/src/runtime/race/race_linux_amd64.syso and b/src/runtime/race/race_linux_amd64.syso differ
diff --git a/src/runtime/race/race_linux_arm64.syso b/src/runtime/race/race_linux_arm64.syso
index f15c5995e6826c26be95d09240d5e5086254b0b6..7c74171b0f33c184c0883477c2b10789d141cee1 100644
Binary files a/src/runtime/race/race_linux_arm64.syso and b/src/runtime/race/race_linux_arm64.syso differ
diff --git a/src/runtime/race/race_linux_ppc64le.syso b/src/runtime/race/race_linux_ppc64le.syso
index 2bf5029659b2e844c4364842c9ccd9537e026c55..a3c72bec556ea2ee90b31bc29d93422a9b15760c 100644
Binary files a/src/runtime/race/race_linux_ppc64le.syso and b/src/runtime/race/race_linux_ppc64le.syso differ
diff --git a/src/runtime/race/syso_test.go b/src/runtime/race/syso_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..db846c5d2ad3c4631a3a5f588a4faec96fd2633c
--- /dev/null
+++ b/src/runtime/race/syso_test.go
@@ -0,0 +1,39 @@
+// Copyright 2020 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.
+
+// +build !android,!js,!ppc64le
+
+// Note: we don't run on Android or ppc64 because if there is any non-race test
+// file in this package, the OS tries to link the .syso file into the
+// test (even when we're not in race mode), which fails. I'm not sure
+// why, but easiest to just punt - as long as a single builder runs
+// this test, we're good.
+
+package race
+
+import (
+ "bytes"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "testing"
+)
+
+func TestIssue37485(t *testing.T) {
+ files, err := filepath.Glob("./*.syso")
+ if err != nil {
+ t.Fatalf("can't find syso files: %s", err)
+ }
+ for _, f := range files {
+ cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), "tool", "nm", f)
+ res, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("nm of %s failed: %s", f, err)
+ continue
+ }
+ if bytes.Contains(res, []byte("getauxval")) {
+ t.Errorf("%s contains getauxval", f)
+ }
+ }
+}
diff --git a/src/sync/runtime2.go b/src/sync/runtime2.go
index 931edad9f1ca61e3437ff8e73afad8f87fa3cded..f10c4e8e0ef3e7e9ee4aefa27825f6a0b7e47296 100644
--- a/src/sync/runtime2.go
+++ b/src/sync/runtime2.go
@@ -1,3 +1,7 @@
+// Copyright 2020 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.
+
// +build !goexperiment.staticlockranking
package sync
diff --git a/src/sync/runtime2_lockrank.go b/src/sync/runtime2_lockrank.go
index 5a68e901fa8839eee35d6b8198294bef18e1de99..aaa1c276261e29a7e34cc014467301cc9d2d226a 100644
--- a/src/sync/runtime2_lockrank.go
+++ b/src/sync/runtime2_lockrank.go
@@ -1,3 +1,7 @@
+// Copyright 2020 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.
+
// +build goexperiment.staticlockranking
package sync
diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go
index 23d7343d3adf8bda5403265775eadd75b4ee89d2..b7351cda82377eae7e77096575b730298435f994 100644
--- a/src/syscall/exec_linux.go
+++ b/src/syscall/exec_linux.go
@@ -465,7 +465,7 @@ nextfd++
}
_, _, err1 = RawSyscall(SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
if _SYS_dup != SYS_DUP3 && err1 == ENOSYS {
- _, _, err1 = RawSyscall(_SYS_dup, uintptr(pipe), uintptr(nextfd), 0)
+ _, _, err1 = RawSyscall(_SYS_dup, uintptr(fd[i]), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
diff --git a/src/testing/testing.go b/src/testing/testing.go
index 85da6bb02a15ba4f5e94741b8578cc259c73eeed..061142b9abd2a736593a625f81ac067abd65d792 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package testing provides support for automated testing of Go packages.
-// It is intended to be used in concert with the ``go test'' command, which automates
+// It is intended to be used in concert with the "go test" command, which automates
// execution of any function of the form
// func TestXxx(*testing.T)
// where Xxx does not start with a lowercase letter. The function name
@@ -14,8 +14,8 @@ //
// To write a new test suite, create a file whose name ends _test.go that
// contains the TestXxx functions as described here. Put the file in the same
// package as the one being tested. The file will be excluded from regular
-// package builds but will be included when the ``go test'' command is run.
-// For more detail, run ``go help test'' and ``go help testflag''.
+// package builds but will be included when the "go test" command is run.
+// For more detail, run "go help test" and "go help testflag".
//
// A simple test function looks like this:
//
diff --git a/test/codegen/memops.go b/test/codegen/memops.go
index cd35910c128d79fb2246adb750fa38bfba0690fe..a2342831460281408c16b217d36c9ce85f2bafad 100644
--- a/test/codegen/memops.go
+++ b/test/codegen/memops.go
@@ -354,3 +354,26 @@ return 0
}
return 1
}
+
+func idxFloatOps(a []float64, b []float32, i int) (float64, float32) {
+ c := float64(7)
+ // amd64: `ADDSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+`
+ c += a[i+1]
+ // amd64: `SUBSD\t16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+`
+ c -= a[i+2]
+ // amd64: `MULSD\t24\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+`
+ c *= a[i+3]
+ // amd64: `DIVSD\t32\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+`
+ c /= a[i+4]
+
+ d := float32(8)
+ // amd64: `ADDSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+`
+ d += b[i+1]
+ // amd64: `SUBSS\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+`
+ d -= b[i+2]
+ // amd64: `MULSS\t12\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+`
+ d *= b[i+3]
+ // amd64: `DIVSS\t16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+`
+ d /= b[i+4]
+ return c, d
+}
diff --git a/test/fixedbugs/issue40367.go b/test/fixedbugs/issue40367.go
new file mode 100644
index 0000000000000000000000000000000000000000..0dc5ad71206733155fa1be42124e9aa73fd05ad2
--- /dev/null
+++ b/test/fixedbugs/issue40367.go
@@ -0,0 +1,41 @@
+// run
+
+// Copyright 2020 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 case1() {
+ rates := []int32{1,2,3,4,5,6}
+ var sink [6]int
+ j := len(sink)
+ for star, _ := range rates {
+ if star+1 < 1 {
+ panic("")
+ }
+ j--
+ sink[j] = j
+ }
+}
+
+func case2() {
+ i := 0
+ var sink [3]int
+ j := len(sink)
+top:
+ j--
+ sink[j] = j
+ if i < 2 {
+ i++
+ if i < 1 {
+ return
+ }
+ goto top
+ }
+}
+
+func main() {
+ case1()
+ case2()
+}
\ No newline at end of file
diff --git a/test/prove.go b/test/prove.go
index d37021d28305ae589156bbbaadbb39e5da32236a..3c19c513b65a61d2a69c4a3e14f7e600f6d82075 100644
--- a/test/prove.go
+++ b/test/prove.go
@@ -670,7 +670,8 @@ func oforuntil(b []int) {
i := 0
if len(b) > i {
top:
- println(b[i]) // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
+ // TODO: remove the todo of next line once we complete the following optimization of CL 244579
+ // println(b[i]) // todo: ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
i++
if i < len(b) {
goto top
@@ -720,7 +721,8 @@
// range2 elements are larger, so they use the general form of a range loop.
func range2(b [][32]int) {
for i, v := range b {
- b[i][0] = v[0] + 1 // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
+ // TODO: remove the todo of next line once we complete the following optimization of CL 244579
+ b[i][0] = v[0] + 1 // todo: ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
if i < len(b) { // ERROR "Proved Less64$"
println("x")
}