aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2018-12-14 19:32:41 -0500
committerFilippo Valsorda <filippo@golang.org>2018-12-14 19:32:41 -0500
commit572c4bce6792d169d467aad26781fa8cab52f8d6 (patch)
treee7c5807794770716336a0756ce3135212b106529
parent35cf0d9f6bbdda847f39d5798f066a64eb91ea4e (diff)
parent4601a4c1b1c00fbe507508f0267ec5a9445bb7e5 (diff)
downloadgo-572c4bce6792d169d467aad26781fa8cab52f8d6.tar.gz
go-572c4bce6792d169d467aad26781fa8cab52f8d6.zip
[dev.boringcrypto.go1.11] all: merge go1.11.4 into dev.boringcrypto.go1.11
Change-Id: I313dfbed32bd65bf400e234b608fcd0efaec7469
-rw-r--r--doc/devel/release.html33
-rw-r--r--doc/go1.11.html10
-rw-r--r--misc/cgo/test/cgo_test.go2
-rw-r--r--misc/cgo/test/issue27340.go12
-rw-r--r--misc/cgo/test/issue27340/a.go42
-rw-r--r--misc/cgo/test/issue28896.go83
-rw-r--r--misc/cgo/test/issue9026/issue9026.go2
-rw-r--r--misc/cgo/test/test27660.go54
-rw-r--r--src/cmd/cgo/gcc.go69
-rw-r--r--src/cmd/compile/internal/gc/main.go8
-rw-r--r--src/cmd/compile/internal/gc/ssa.go21
-rw-r--r--src/cmd/compile/internal/gc/subr.go2
-rw-r--r--src/cmd/compile/internal/gc/typecheck.go24
-rw-r--r--src/cmd/compile/internal/ssa/softfloat.go14
-rw-r--r--src/cmd/go/internal/get/get.go23
-rw-r--r--src/cmd/go/internal/get/path.go192
-rw-r--r--src/cmd/go/internal/get/vcs.go18
-rw-r--r--src/cmd/go/internal/modfetch/coderepo.go5
-rw-r--r--src/cmd/go/internal/run/run.go3
-rw-r--r--src/cmd/go/internal/work/exec.go13
-rw-r--r--src/cmd/go/testdata/script/get_brace.txt49
-rw-r--r--src/cmd/go/testdata/script/get_dotfiles.txt61
-rw-r--r--src/cmd/go/testdata/script/get_tilde.txt21
-rw-r--r--src/cmd/go/testdata/script/get_unicode.txt37
-rw-r--r--src/cmd/go/testdata/script/mod_go_version.txt16
-rw-r--r--src/cmd/go/testdata/script/run_wildcard.txt5
-rw-r--r--src/cmd/link/internal/ld/lib.go1
-rw-r--r--src/crypto/x509/cert_pool.go28
-rw-r--r--src/crypto/x509/verify.go86
-rw-r--r--src/crypto/x509/verify_test.go119
-rw-r--r--src/go/types/resolver.go18
-rw-r--r--src/go/types/stdlib_test.go1
-rw-r--r--src/net/http/h2_bundle.go2
-rw-r--r--src/runtime/cgocall.go28
-rw-r--r--src/runtime/os_linux_arm64.go12
-rw-r--r--src/runtime/stack.go7
-rw-r--r--test/fixedbugs/issue18640.go5
-rw-r--r--test/fixedbugs/issue23823.go8
-rw-r--r--test/fixedbugs/issue24939.go4
-rw-r--r--test/fixedbugs/issue27232.go19
-rw-r--r--test/fixedbugs/issue27267.go21
-rw-r--r--test/fixedbugs/issue27695c.go65
-rw-r--r--test/fixedbugs/issue28616.go25
-rw-r--r--test/fixedbugs/issue28688.go31
-rw-r--r--test/fixedbugs/issue28797.go53
-rw-r--r--test/loopbce.go94
-rw-r--r--test/prove.go18
-rw-r--r--test/run.go2
48 files changed, 1279 insertions, 187 deletions
diff --git a/doc/devel/release.html b/doc/devel/release.html
index b02efed501..73f7a0e304 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -49,6 +49,23 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.2">Go
1.11.2 milestone</a> on our issue tracker for details.
</p>
+<p>
+go1.11.3 (released 2018/12/12) includes three security fixes to "go get" and
+the <code>crypto/x509</code> package.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.3">Go
+1.11.3 milestone</a> on our issue tracker for details.
+</p>
+
+<p>
+go1.11.4 (released 2018/12/14) includes fixes to cgo, the compiler, linker,
+runtime, documentation, go command, and the <code>net/http</code> and
+<code>go/types</code> packages.
+It includes a fix to a bug introduced in Go 1.11.3 that broke <code>go</code>
+<code>get</code> for import path patterns containing "<code>...</code>".
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.4+label%3ACherryPickApproved">Go
+1.11.4 milestone</a> on our issue tracker for details.
+</p>
+
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
<p>
@@ -98,6 +115,22 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.5">Go
1.10.5 milestone</a> on our issue tracker for details.
</p>
+<p>
+go1.10.6 (released 2018/12/12) includes three security fixes to "go get" and
+the <code>crypto/x509</code> package.
+It contains the same fixes as Go 1.11.3 and was released at the same time.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.6">Go
+1.10.6 milestone</a> on our issue tracker for details.
+</p>
+
+<p>
+go1.10.7 (released 2018/12/14) includes a fix to a bug introduced in Go 1.10.6
+that broke <code>go</code> <code>get</code> for import path patterns containing
+"<code>...</code>".
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.7+label%3ACherryPickApproved">
+Go 1.10.7 milestone</a> on our issue tracker for details.
+</p>
+
<h2 id="go1.9">go1.9 (released 2017/08/24)</h2>
<p>
diff --git a/doc/go1.11.html b/doc/go1.11.html
index 16b4c904cb..1d85be9fe4 100644
--- a/doc/go1.11.html
+++ b/doc/go1.11.html
@@ -400,6 +400,16 @@ details. <!-- CL 126275, CL 127156, CL 122217, CL 122575, CL 123177 -->
information.
</p>
+<h3 id="run">Run</h3>
+
+<p>
+ <!-- CL 109341 -->
+ The <a href="/cmd/go/"><code>go</code>&nbsp;<code>run</code></a>
+ command now allows a single import path, a directory name or a
+ pattern matching a single package.
+ This allows <code>go</code>&nbsp;<code>run</code>&nbsp;<code>pkg</code> or <code>go</code>&nbsp;<code>run</code>&nbsp;<code>dir</code>, most importantly <code>go</code>&nbsp;<code>run</code>&nbsp;<code>.</code>
+</p>
+
<h2 id="runtime">Runtime</h2>
<p><!-- CL 85887 -->
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index ccacc50fe1..242ba6c0e5 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -92,6 +92,8 @@ func Test25143(t *testing.T) { test25143(t) }
func Test23356(t *testing.T) { test23356(t) }
func Test26066(t *testing.T) { test26066(t) }
func Test26213(t *testing.T) { test26213(t) }
+func Test27660(t *testing.T) { test27660(t) }
+func Test28896(t *testing.T) { test28896(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
diff --git a/misc/cgo/test/issue27340.go b/misc/cgo/test/issue27340.go
new file mode 100644
index 0000000000..f8c8a87f20
--- /dev/null
+++ b/misc/cgo/test/issue27340.go
@@ -0,0 +1,12 @@
+// Copyright 2018 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.
+
+// Failed to resolve typedefs consistently.
+// No runtime test; just make sure it compiles.
+
+package cgotest
+
+import "./issue27340"
+
+var issue27340Var = issue27340.Issue27340GoFunc
diff --git a/misc/cgo/test/issue27340/a.go b/misc/cgo/test/issue27340/a.go
new file mode 100644
index 0000000000..f5b120c1fd
--- /dev/null
+++ b/misc/cgo/test/issue27340/a.go
@@ -0,0 +1,42 @@
+// Copyright 2018 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.
+
+// Failed to resolve typedefs consistently.
+// No runtime test; just make sure it compiles.
+// In separate directory to isolate #pragma GCC diagnostic.
+
+package issue27340
+
+// We use the #pragma to avoid a compiler warning about incompatible
+// pointer types, because we generate code passing a struct ptr rather
+// than using the typedef. This warning is expected and does not break
+// a normal build.
+// We can only disable -Wincompatible-pointer-types starting with GCC 5.
+
+// #if __GNU_MAJOR__ >= 5
+//
+// #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
+//
+// typedef struct {
+// int a;
+// } issue27340Struct, *issue27340Ptr;
+//
+// static void issue27340CFunc(issue27340Ptr p) {}
+//
+// #else /* _GNU_MAJOR_ < 5 */
+//
+// typedef struct {
+// int a;
+// } issue27340Struct;
+//
+// static issue27340Struct* issue27340Ptr(issue27340Struct* p) { return p; }
+//
+// static void issue27340CFunc(issue27340Struct *p) {}
+// #endif /* _GNU_MAJOR_ < 5 */
+import "C"
+
+func Issue27340GoFunc() {
+ var s C.issue27340Struct
+ C.issue27340CFunc(C.issue27340Ptr(&s))
+}
diff --git a/misc/cgo/test/issue28896.go b/misc/cgo/test/issue28896.go
new file mode 100644
index 0000000000..8796040f18
--- /dev/null
+++ b/misc/cgo/test/issue28896.go
@@ -0,0 +1,83 @@
+// Copyright 2018 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.
+
+// cgo was incorrectly adding padding after a packed struct.
+
+package cgotest
+
+/*
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef struct {
+ void *f1;
+ uint32_t f2;
+} __attribute__((__packed__)) innerPacked;
+
+typedef struct {
+ innerPacked g1;
+ uint64_t g2;
+} outerPacked;
+
+typedef struct {
+ void *f1;
+ uint32_t f2;
+} innerUnpacked;
+
+typedef struct {
+ innerUnpacked g1;
+ uint64_t g2;
+} outerUnpacked;
+
+size_t offset(int x) {
+ switch (x) {
+ case 0:
+ return offsetof(innerPacked, f2);
+ case 1:
+ return offsetof(outerPacked, g2);
+ case 2:
+ return offsetof(innerUnpacked, f2);
+ case 3:
+ return offsetof(outerUnpacked, g2);
+ default:
+ abort();
+ }
+}
+*/
+import "C"
+
+import (
+ "testing"
+ "unsafe"
+)
+
+func offset(i int) uintptr {
+ var pi C.innerPacked
+ var po C.outerPacked
+ var ui C.innerUnpacked
+ var uo C.outerUnpacked
+ switch i {
+ case 0:
+ return unsafe.Offsetof(pi.f2)
+ case 1:
+ return unsafe.Offsetof(po.g2)
+ case 2:
+ return unsafe.Offsetof(ui.f2)
+ case 3:
+ return unsafe.Offsetof(uo.g2)
+ default:
+ panic("can't happen")
+ }
+}
+
+func test28896(t *testing.T) {
+ for i := 0; i < 4; i++ {
+ c := uintptr(C.offset(C.int(i)))
+ g := offset(i)
+ if c != g {
+ t.Errorf("%d: C: %d != Go %d", i, c, g)
+ }
+ }
+}
diff --git a/misc/cgo/test/issue9026/issue9026.go b/misc/cgo/test/issue9026/issue9026.go
index 0af86e64da..149c26562a 100644
--- a/misc/cgo/test/issue9026/issue9026.go
+++ b/misc/cgo/test/issue9026/issue9026.go
@@ -29,7 +29,7 @@ func Test(t *testing.T) {
// Brittle: the assertion may fail spuriously when the algorithm
// changes, but should remain stable otherwise.
got := fmt.Sprintf("%T %T", in, opts)
- want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___1"
+ want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___0"
if got != want {
t.Errorf("Non-deterministic type names: got %s, want %s", got, want)
}
diff --git a/misc/cgo/test/test27660.go b/misc/cgo/test/test27660.go
new file mode 100644
index 0000000000..8c23b7dc58
--- /dev/null
+++ b/misc/cgo/test/test27660.go
@@ -0,0 +1,54 @@
+// Copyright 2018 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.
+
+// Stress the interaction between the race detector and cgo in an
+// attempt to reproduce the memory corruption described in #27660.
+// The bug was very timing sensitive; at the time of writing this
+// test would only trigger the bug about once out of every five runs.
+
+package cgotest
+
+// #include <unistd.h>
+import "C"
+
+import (
+ "context"
+ "math/rand"
+ "runtime"
+ "sync"
+ "testing"
+ "time"
+)
+
+func test27660(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ ints := make([]int, 100)
+ locks := make([]sync.Mutex, 100)
+ // Slowly create threads so that ThreadSanitizer is forced to
+ // frequently resize its SyncClocks.
+ for i := 0; i < 100; i++ {
+ go func() {
+ for ctx.Err() == nil {
+ // Sleep in C for long enough that it is likely that the runtime
+ // will retake this goroutine's currently wired P.
+ C.usleep(1000 /* 1ms */)
+ runtime.Gosched() // avoid starvation (see #28701)
+ }
+ }()
+ go func() {
+ // Trigger lots of synchronization and memory reads/writes to
+ // increase the likelihood that the race described in #27660
+ // results in corruption of ThreadSanitizer's internal state
+ // and thus an assertion failure or segfault.
+ for ctx.Err() == nil {
+ j := rand.Intn(100)
+ locks[j].Lock()
+ ints[j]++
+ locks[j].Unlock()
+ }
+ }()
+ time.Sleep(time.Millisecond)
+ }
+}
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 20e794b4be..c2f089ee39 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -163,6 +163,10 @@ func (p *Package) Translate(f *File) {
// Convert C.ulong to C.unsigned long, etc.
cref.Name.C = cname(cref.Name.Go)
}
+
+ var conv typeConv
+ conv.Init(p.PtrSize, p.IntSize)
+
p.loadDefines(f)
p.typedefs = map[string]bool{}
p.typedefList = nil
@@ -178,7 +182,7 @@ func (p *Package) Translate(f *File) {
}
needType := p.guessKinds(f)
if len(needType) > 0 {
- p.loadDWARF(f, needType)
+ p.loadDWARF(f, &conv, needType)
}
// In godefs mode we're OK with the typedefs, which
@@ -472,7 +476,7 @@ func (p *Package) guessKinds(f *File) []*Name {
// loadDWARF parses the DWARF debug information generated
// by gcc to learn the details of the constants, variables, and types
// being referred to as C.xxx.
-func (p *Package) loadDWARF(f *File, names []*Name) {
+func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
// Extract the types from the DWARF section of an object
// from a well-formed C program. Gcc only generates DWARF info
// for symbols in the object file, so it is not enough to print the
@@ -579,8 +583,6 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
}
// Record types and typedef information.
- var conv typeConv
- conv.Init(p.PtrSize, p.IntSize)
for i, n := range names {
if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" {
conv.getTypeIDs[n.Go[:len(n.Go)-9]] = true
@@ -1734,10 +1736,10 @@ func runGcc(stdin []byte, args []string) (string, string) {
// with equivalent memory layout.
type typeConv struct {
// Cache of already-translated or in-progress types.
- m map[dwarf.Type]*Type
+ m map[string]*Type
// Map from types to incomplete pointers to those types.
- ptrs map[dwarf.Type][]*Type
+ ptrs map[string][]*Type
// Keys of ptrs in insertion order (deterministic worklist)
// ptrKeys contains exactly the keys in ptrs.
ptrKeys []dwarf.Type
@@ -1772,8 +1774,8 @@ var unionWithPointer = make(map[ast.Expr]bool)
func (c *typeConv) Init(ptrSize, intSize int64) {
c.ptrSize = ptrSize
c.intSize = intSize
- c.m = make(map[dwarf.Type]*Type)
- c.ptrs = make(map[dwarf.Type][]*Type)
+ c.m = make(map[string]*Type)
+ c.ptrs = make(map[string][]*Type)
c.getTypeIDs = make(map[string]bool)
c.bool = c.Ident("bool")
c.byte = c.Ident("byte")
@@ -1881,11 +1883,12 @@ func (c *typeConv) FinishType(pos token.Pos) {
// Keep looping until they're all done.
for len(c.ptrKeys) > 0 {
dtype := c.ptrKeys[0]
+ dtypeKey := dtype.String()
c.ptrKeys = c.ptrKeys[1:]
- ptrs := c.ptrs[dtype]
- delete(c.ptrs, dtype)
+ ptrs := c.ptrs[dtypeKey]
+ delete(c.ptrs, dtypeKey)
- // Note Type might invalidate c.ptrs[dtype].
+ // Note Type might invalidate c.ptrs[dtypeKey].
t := c.Type(dtype, pos)
for _, ptr := range ptrs {
ptr.Go.(*ast.StarExpr).X = t.Go
@@ -1897,18 +1900,29 @@ func (c *typeConv) FinishType(pos token.Pos) {
// Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field.
func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
- if t, ok := c.m[dtype]; ok {
- if t.Go == nil {
- fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
+ // Always recompute bad pointer typedefs, as the set of such
+ // typedefs changes as we see more types.
+ checkCache := true
+ if dtt, ok := dtype.(*dwarf.TypedefType); ok && c.badPointerTypedef(dtt) {
+ checkCache = false
+ }
+
+ key := dtype.String()
+
+ if checkCache {
+ if t, ok := c.m[key]; ok {
+ if t.Go == nil {
+ fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
+ }
+ return t
}
- return t
}
t := new(Type)
t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
t.Align = -1
t.C = &TypeRepr{Repr: dtype.Common().Name}
- c.m[dtype] = t
+ c.m[key] = t
switch dt := dtype.(type) {
default:
@@ -2071,10 +2085,11 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
// Placeholder initialization; completed in FinishType.
t.Go = &ast.StarExpr{}
t.C.Set("<incomplete>*")
- if _, ok := c.ptrs[dt.Type]; !ok {
+ key := dt.Type.String()
+ if _, ok := c.ptrs[key]; !ok {
c.ptrKeys = append(c.ptrKeys, dt.Type)
}
- c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
+ c.ptrs[key] = append(c.ptrs[key], t)
case *dwarf.QualType:
t1 := c.Type(dt.Type, pos)
@@ -2462,11 +2477,6 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
anon := 0
for _, f := range dt.Field {
- if f.ByteOffset > off {
- fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
- off = f.ByteOffset
- }
-
name := f.Name
ft := f.Type
@@ -2515,6 +2525,19 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
// structs are in system headers that cannot be corrected.
continue
}
+
+ // Round off up to talign, assumed to be a power of 2.
+ off = (off + talign - 1) &^ (talign - 1)
+
+ if f.ByteOffset > off {
+ fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
+ off = f.ByteOffset
+ }
+ if f.ByteOffset < off {
+ // Drop a packed field that we can't represent.
+ continue
+ }
+
n := len(fld)
fld = fld[0 : n+1]
if name == "" {
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 9f1ea2ab4b..6d8086f750 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -481,13 +481,17 @@ func Main(archInit func(*Arch)) {
// Phase 1: const, type, and names and types of funcs.
// This will gather all the information about types
// and methods but doesn't depend on any of it.
+ //
+ // We also defer type alias declarations until phase 2
+ // to avoid cycles like #18640.
+ // TODO(gri) Remove this again once we have a fix for #25838.
defercheckwidth()
// Don't use range--typecheck can add closures to xtop.
timings.Start("fe", "typecheck", "top1")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op; op != ODCL && op != OAS && op != OAS2 {
+ if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
xtop[i] = typecheck(n, Etop)
}
}
@@ -499,7 +503,7 @@ func Main(archInit func(*Arch)) {
timings.Start("fe", "typecheck", "top2")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op; op == ODCL || op == OAS || op == OAS2 {
+ if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
xtop[i] = typecheck(n, Etop)
}
}
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index af43da6275..5b84a0a5bb 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -3863,6 +3863,18 @@ func (s *state) boundsCheck(idx, len *ssa.Value) {
s.check(cmp, panicindex)
}
+func couldBeNegative(v *ssa.Value) bool {
+ switch v.Op {
+ case ssa.OpSliceLen, ssa.OpSliceCap, ssa.OpStringLen:
+ return false
+ case ssa.OpConst64:
+ return v.AuxInt < 0
+ case ssa.OpConst32:
+ return int32(v.AuxInt) < 0
+ }
+ return true
+}
+
// sliceBoundsCheck generates slice bounds checking code. Checks if 0 <= idx <= len, branches to exit if not.
// Starts a new block on return.
// idx and len are already converted to full int width.
@@ -3870,6 +3882,15 @@ func (s *state) sliceBoundsCheck(idx, len *ssa.Value) {
if Debug['B'] != 0 {
return
}
+ if couldBeNegative(len) {
+ // OpIsSliceInBounds requires second arg not negative; if it's not obviously true, must check.
+ cmpop := ssa.OpGeq64
+ if len.Type.Size() == 4 {
+ cmpop = ssa.OpGeq32
+ }
+ cmp := s.newValue2(cmpop, types.Types[TBOOL], len, s.zeroVal(len.Type))
+ s.check(cmp, panicslice)
+ }
// bounds check
cmp := s.newValue2(ssa.OpIsSliceInBounds, types.Types[TBOOL], idx, len)
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 0af0ff82c4..c926b147de 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -1116,7 +1116,7 @@ func calcHasCall(n *Node) bool {
// When using soft-float, these ops might be rewritten to function calls
// so we ensure they are evaluated first.
- case OADD, OSUB, OMINUS:
+ case OADD, OSUB, OMINUS, OMUL:
if thearch.SoftFloat && (isFloat[n.Type.Etype] || isComplex[n.Type.Etype]) {
return true
}
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index bf7090518c..74b8764933 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -202,8 +202,16 @@ func typecheck(n *Node, top int) *Node {
// since it would expand indefinitely when aliases
// are substituted.
cycle := cycleFor(n)
- for _, n := range cycle {
- if n.Name != nil && !n.Name.Param.Alias {
+ for _, n1 := range cycle {
+ if n1.Name != nil && !n1.Name.Param.Alias {
+ // Cycle is ok. But if n is an alias type and doesn't
+ // have a type yet, we have a recursive type declaration
+ // with aliases that we can't handle properly yet.
+ // Report an error rather than crashing later.
+ if n.Name != nil && n.Name.Param.Alias && n.Type == nil {
+ lineno = n.Pos
+ Fatalf("cannot handle alias type declaration (issue #25838): %v", n)
+ }
lineno = lno
return n
}
@@ -3987,6 +3995,12 @@ func deadcode(fn *Node) {
}
func deadcodeslice(nn Nodes) {
+ var lastLabel = -1
+ for i, n := range nn.Slice() {
+ if n != nil && n.Op == OLABEL {
+ lastLabel = i
+ }
+ }
for i, n := range nn.Slice() {
// Cut is set to true when all nodes after i'th position
// should be removed.
@@ -4009,10 +4023,14 @@ func deadcodeslice(nn Nodes) {
// If "then" or "else" branch ends with panic or return statement,
// it is safe to remove all statements after this node.
// isterminating is not used to avoid goto-related complications.
+ // We must be careful not to deadcode-remove labels, as they
+ // might be the target of a goto. See issue 28616.
if body := body.Slice(); len(body) != 0 {
switch body[(len(body) - 1)].Op {
case ORETURN, ORETJMP, OPANIC:
- cut = true
+ if i > lastLabel {
+ cut = true
+ }
}
}
}
diff --git a/src/cmd/compile/internal/ssa/softfloat.go b/src/cmd/compile/internal/ssa/softfloat.go
index 39829b046c..4afb94057d 100644
--- a/src/cmd/compile/internal/ssa/softfloat.go
+++ b/src/cmd/compile/internal/ssa/softfloat.go
@@ -4,7 +4,10 @@
package ssa
-import "math"
+import (
+ "cmd/compile/internal/types"
+ "math"
+)
func softfloat(f *Func) {
if !f.Config.SoftFloat {
@@ -53,6 +56,15 @@ func softfloat(f *Func) {
v.Type = f.Config.Types.UInt64
}
newInt64 = newInt64 || v.Type.Size() == 8
+ } else if (v.Op == OpStore || v.Op == OpZero || v.Op == OpMove) && v.Aux.(*types.Type).IsFloat() {
+ switch size := v.Aux.(*types.Type).Size(); size {
+ case 4:
+ v.Aux = f.Config.Types.UInt32
+ case 8:
+ v.Aux = f.Config.Types.UInt64
+ default:
+ v.Fatalf("bad float type with size %d", size)
+ }
}
}
}
diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go
index e4148bceb0..a314c57160 100644
--- a/src/cmd/go/internal/get/get.go
+++ b/src/cmd/go/internal/get/get.go
@@ -232,7 +232,7 @@ var downloadCache = map[string]bool{}
var downloadRootCache = map[string]bool{}
// download runs the download half of the get command
-// for the package named by the argument.
+// for the package or pattern named by the argument.
func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
if mode&load.ResolveImport != 0 {
// Caller is responsible for expanding vendor paths.
@@ -402,6 +402,23 @@ func downloadPackage(p *load.Package) error {
security = web.Insecure
}
+ // p can be either a real package, or a pseudo-package whose “import path” is
+ // actually a wildcard pattern.
+ // Trim the path at the element containing the first wildcard,
+ // and hope that it applies to the wildcarded parts too.
+ // This makes 'go get rsc.io/pdf/...' work in a fresh GOPATH.
+ importPrefix := p.ImportPath
+ if i := strings.Index(importPrefix, "..."); i >= 0 {
+ slash := strings.LastIndexByte(importPrefix[:i], '/')
+ if slash < 0 {
+ return fmt.Errorf("cannot expand ... in %q", p.ImportPath)
+ }
+ importPrefix = importPrefix[:slash]
+ }
+ if err := CheckImportPath(importPrefix); err != nil {
+ return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err)
+ }
+
if p.Internal.Build.SrcRoot != "" {
// Directory exists. Look for checkout along path to src.
vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
@@ -421,7 +438,7 @@ func downloadPackage(p *load.Package) error {
}
repo = remote
if !*getF && err == nil {
- if rr, err := RepoRootForImportPath(p.ImportPath, IgnoreMod, security); err == nil {
+ if rr, err := RepoRootForImportPath(importPrefix, IgnoreMod, security); err == nil {
repo := rr.Repo
if rr.vcs.resolveRepo != nil {
resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
@@ -438,7 +455,7 @@ func downloadPackage(p *load.Package) error {
} else {
// Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository.
- rr, err := RepoRootForImportPath(p.ImportPath, IgnoreMod, security)
+ rr, err := RepoRootForImportPath(importPrefix, IgnoreMod, security)
if err != nil {
return err
}
diff --git a/src/cmd/go/internal/get/path.go b/src/cmd/go/internal/get/path.go
new file mode 100644
index 0000000000..d443bd28a9
--- /dev/null
+++ b/src/cmd/go/internal/get/path.go
@@ -0,0 +1,192 @@
+// Copyright 2018 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 get
+
+import (
+ "fmt"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// The following functions are copied verbatim from cmd/go/internal/module/module.go,
+// with a change to additionally reject Windows short-names,
+// and one to accept arbitrary letters (golang.org/issue/29101).
+//
+// TODO(bcmills): After the call site for this function is backported,
+// consolidate this back down to a single copy.
+//
+// NOTE: DO NOT MERGE THESE UNTIL WE DECIDE ABOUT ARBITRARY LETTERS IN MODULE MODE.
+
+// CheckImportPath checks that an import path is valid.
+func CheckImportPath(path string) error {
+ if err := checkPath(path, false); err != nil {
+ return fmt.Errorf("malformed import path %q: %v", path, err)
+ }
+ return nil
+}
+
+// checkPath checks that a general path is valid.
+// It returns an error describing why but not mentioning path.
+// Because these checks apply to both module paths and import paths,
+// the caller is expected to add the "malformed ___ path %q: " prefix.
+// fileName indicates whether the final element of the path is a file name
+// (as opposed to a directory name).
+func checkPath(path string, fileName bool) error {
+ if !utf8.ValidString(path) {
+ return fmt.Errorf("invalid UTF-8")
+ }
+ if path == "" {
+ return fmt.Errorf("empty string")
+ }
+ if strings.Contains(path, "..") {
+ return fmt.Errorf("double dot")
+ }
+ if strings.Contains(path, "//") {
+ return fmt.Errorf("double slash")
+ }
+ if path[len(path)-1] == '/' {
+ return fmt.Errorf("trailing slash")
+ }
+ elemStart := 0
+ for i, r := range path {
+ if r == '/' {
+ if err := checkElem(path[elemStart:i], fileName); err != nil {
+ return err
+ }
+ elemStart = i + 1
+ }
+ }
+ if err := checkElem(path[elemStart:], fileName); err != nil {
+ return err
+ }
+ return nil
+}
+
+// checkElem checks whether an individual path element is valid.
+// fileName indicates whether the element is a file name (not a directory name).
+func checkElem(elem string, fileName bool) error {
+ if elem == "" {
+ return fmt.Errorf("empty path element")
+ }
+ if strings.Count(elem, ".") == len(elem) {
+ return fmt.Errorf("invalid path element %q", elem)
+ }
+ if elem[0] == '.' && !fileName {
+ return fmt.Errorf("leading dot in path element")
+ }
+ if elem[len(elem)-1] == '.' {
+ return fmt.Errorf("trailing dot in path element")
+ }
+
+ charOK := pathOK
+ if fileName {
+ charOK = fileNameOK
+ }
+ for _, r := range elem {
+ if !charOK(r) {
+ return fmt.Errorf("invalid char %q", r)
+ }
+ }
+
+ // Windows disallows a bunch of path elements, sadly.
+ // See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
+ short := elem
+ if i := strings.Index(short, "."); i >= 0 {
+ short = short[:i]
+ }
+ for _, bad := range badWindowsNames {
+ if strings.EqualFold(bad, short) {
+ return fmt.Errorf("disallowed path element %q", elem)
+ }
+ }
+
+ // Reject path components that look like Windows short-names.
+ // Those usually end in a tilde followed by one or more ASCII digits.
+ if tilde := strings.LastIndexByte(short, '~'); tilde >= 0 && tilde < len(short)-1 {
+ suffix := short[tilde+1:]
+ suffixIsDigits := true
+ for _, r := range suffix {
+ if r < '0' || r > '9' {
+ suffixIsDigits = false
+ break
+ }
+ }
+ if suffixIsDigits {
+ return fmt.Errorf("trailing tilde and digits in path element")
+ }
+ }
+
+ return nil
+}
+
+// pathOK reports whether r can appear in an import path element.
+//
+// NOTE: This function DIVERGES from module mode pathOK by accepting Unicode letters.
+func pathOK(r rune) bool {
+ if r < utf8.RuneSelf {
+ return r == '+' || r == '-' || r == '.' || r == '_' || r == '~' ||
+ '0' <= r && r <= '9' ||
+ 'A' <= r && r <= 'Z' ||
+ 'a' <= r && r <= 'z'
+ }
+ return unicode.IsLetter(r)
+}
+
+// fileNameOK reports whether r can appear in a file name.
+// For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters.
+// If we expand the set of allowed characters here, we have to
+// work harder at detecting potential case-folding and normalization collisions.
+// See note about "safe encoding" below.
+func fileNameOK(r rune) bool {
+ if r < utf8.RuneSelf {
+ // Entire set of ASCII punctuation, from which we remove characters:
+ // ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
+ // We disallow some shell special characters: " ' * < > ? ` |
+ // (Note that some of those are disallowed by the Windows file system as well.)
+ // We also disallow path separators / : and \ (fileNameOK is only called on path element characters).
+ // We allow spaces (U+0020) in file names.
+ const allowed = "!#$%&()+,-.=@[]^_{}~ "
+ if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' {
+ return true
+ }
+ for i := 0; i < len(allowed); i++ {
+ if rune(allowed[i]) == r {
+ return true
+ }
+ }
+ return false
+ }
+ // It may be OK to add more ASCII punctuation here, but only carefully.
+ // For example Windows disallows < > \, and macOS disallows :, so we must not allow those.
+ return unicode.IsLetter(r)
+}
+
+// badWindowsNames are the reserved file path elements on Windows.
+// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
+var badWindowsNames = []string{
+ "CON",
+ "PRN",
+ "AUX",
+ "NUL",
+ "COM1",
+ "COM2",
+ "COM3",
+ "COM4",
+ "COM5",
+ "COM6",
+ "COM7",
+ "COM8",
+ "COM9",
+ "LPT1",
+ "LPT2",
+ "LPT3",
+ "LPT4",
+ "LPT5",
+ "LPT6",
+ "LPT7",
+ "LPT8",
+ "LPT9",
+}
diff --git a/src/cmd/go/internal/get/vcs.go b/src/cmd/go/internal/get/vcs.go
index 5cd164f2ff..baf9b1b01e 100644
--- a/src/cmd/go/internal/get/vcs.go
+++ b/src/cmd/go/internal/get/vcs.go
@@ -647,14 +647,7 @@ const (
func RepoRootForImportPath(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) {
rr, err := repoRootFromVCSPaths(importPath, "", security, vcsPaths)
if err == errUnknownSite {
- // If there are wildcards, look up the thing before the wildcard,
- // hoping it applies to the wildcarded parts too.
- // This makes 'go get rsc.io/pdf/...' work in a fresh GOPATH.
- lookup := strings.TrimSuffix(importPath, "/...")
- if i := strings.Index(lookup, "/.../"); i >= 0 {
- lookup = lookup[:i]
- }
- rr, err = repoRootForImportDynamic(lookup, mod, security)
+ rr, err = repoRootForImportDynamic(importPath, mod, security)
if err != nil {
err = fmt.Errorf("unrecognized import path %q (%v)", importPath, err)
}
@@ -667,6 +660,7 @@ func RepoRootForImportPath(importPath string, mod ModuleMode, security web.Secur
}
}
+ // Should have been taken care of above, but make sure.
if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {
// Do not allow wildcards in the repo root.
rr = nil
@@ -966,10 +960,14 @@ func matchGoImport(imports []metaImport, importPath string) (metaImport, error)
// expand rewrites s to replace {k} with match[k] for each key k in match.
func expand(match map[string]string, s string) string {
+ // We want to replace each match exactly once, and the result of expansion
+ // must not depend on the iteration order through the map.
+ // A strings.Replacer has exactly the properties we're looking for.
+ oldNew := make([]string, 0, 2*len(match))
for k, v := range match {
- s = strings.Replace(s, "{"+k+"}", v, -1)
+ oldNew = append(oldNew, "{"+k+"}", v)
}
- return s
+ return strings.NewReplacer(oldNew...).Replace(s)
}
// vcsPaths defines the meaning of import paths referring to
diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go
index 9cf0e91150..2e825e7cf7 100644
--- a/src/cmd/go/internal/modfetch/coderepo.go
+++ b/src/cmd/go/internal/modfetch/coderepo.go
@@ -498,6 +498,11 @@ func (r *codeRepo) Zip(version string, tmpdir string) (tmpfile string, err error
}
}
for _, zf := range zr.File {
+ if !zf.FileInfo().Mode().IsRegular() {
+ // Skip symlinks (golang.org/issue/27093).
+ continue
+ }
+
if topPrefix == "" {
i := strings.Index(zf.Name, "/")
if i < 0 {
diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go
index 303e6842e7..feccf23b27 100644
--- a/src/cmd/go/internal/run/run.go
+++ b/src/cmd/go/internal/run/run.go
@@ -78,6 +78,9 @@ func runRun(cmd *base.Command, args []string) {
p = load.GoFilesPackage(files)
} else if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
pkgs := load.PackagesAndErrors(args[:1])
+ if len(pkgs) == 0 {
+ base.Fatalf("go run: no packages loaded from %s", args[0])
+ }
if len(pkgs) > 1 {
var names []string
for _, p := range pkgs {
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 91c4816fd0..88d9e6453f 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -434,10 +434,6 @@ func (b *Builder) build(a *Action) (err error) {
return fmt.Errorf("missing or invalid binary-only package; expected file %q", a.Package.Target)
}
- if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
- return fmt.Errorf("module requires Go %s", p.Module.GoVersion)
- }
-
if err := b.Mkdir(a.Objdir); err != nil {
return err
}
@@ -638,12 +634,19 @@ func (b *Builder) build(a *Action) (err error) {
objpkg := objdir + "_pkg_.a"
ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles)
if len(out) > 0 {
- b.showOutput(a, a.Package.Dir, a.Package.Desc(), b.processOutput(out))
+ output := b.processOutput(out)
+ if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
+ output += "note: module requires Go " + p.Module.GoVersion
+ }
+ b.showOutput(a, a.Package.Dir, a.Package.Desc(), output)
if err != nil {
return errPrintedOutput
}
}
if err != nil {
+ if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
+ b.showOutput(a, a.Package.Dir, a.Package.Desc(), "note: module requires Go "+p.Module.GoVersion)
+ }
return err
}
if ofile != objpkg {
diff --git a/src/cmd/go/testdata/script/get_brace.txt b/src/cmd/go/testdata/script/get_brace.txt
new file mode 100644
index 0000000000..be81d8f487
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_brace.txt
@@ -0,0 +1,49 @@
+[!exec:git] skip
+
+# Set up some empty repositories.
+cd $WORK/_origin/foo
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+cd $WORK
+cd '_origin/{confusing}'
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+# Clone the empty repositories into GOPATH.
+# This tells the Go command where to find them: it takes the place of a user's meta-tag redirector.
+mkdir $GOPATH/src/example.com
+cd $GOPATH/src/example.com
+exec git clone $WORK/_origin/foo
+exec git clone $WORK/_origin/{confusing}
+
+# Commit contents to the repositories.
+cd $WORK/_origin/foo
+exec git add main.go
+exec git commit -m 'add main'
+
+cd $WORK
+cd '_origin/{confusing}'
+exec git add confusing.go
+exec git commit -m 'just try to delete this!'
+
+# 'go get' should refuse to download or update the confusingly-named repo.
+cd $GOPATH/src/example.com/foo
+! go get -u 'example.com/{confusing}'
+stderr 'invalid char'
+! go get -u example.com/foo
+stderr 'invalid import path'
+! exists example.com/{confusing}
+
+-- $WORK/_origin/foo/main.go --
+package main
+import _ "example.com/{confusing}"
+
+func main() {}
+
+-- $WORK/_origin/{confusing}/confusing.go --
+package confusing
diff --git a/src/cmd/go/testdata/script/get_dotfiles.txt b/src/cmd/go/testdata/script/get_dotfiles.txt
new file mode 100644
index 0000000000..1876114362
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_dotfiles.txt
@@ -0,0 +1,61 @@
+[!exec:git] skip
+
+# Set up a benign repository and a repository with a dotfile name.
+cd $WORK/_origin/foo
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+cd $WORK/_origin/.hidden
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+# Clone the empty repositories into GOPATH.
+# This tells the Go command where to find them: it takes the place of a user's meta-tag redirector.
+mkdir $GOPATH/src/example.com
+cd $GOPATH/src/example.com
+exec git clone $WORK/_origin/foo
+exec git clone $WORK/_origin/.hidden
+
+# Add a benign commit.
+cd $WORK/_origin/foo
+cp _ok/main.go main.go
+exec git add main.go
+exec git commit -m 'add ok'
+
+# 'go get' should install the benign commit.
+cd $GOPATH
+go get -u example.com/foo
+
+# Now sneak in an import of a dotfile path.
+cd $WORK/_origin/.hidden
+exec git add hidden.go
+exec git commit -m 'nothing to see here, move along'
+
+cd $WORK/_origin/foo
+cp _sneaky/main.go main.go
+exec git add main.go
+exec git commit -m 'fix typo (heh heh heh)'
+
+# 'go get -u' should refuse to download or update the dotfile-named repo.
+cd $GOPATH/src/example.com/foo
+! go get -u example.com/foo
+stderr 'leading dot'
+! exists example.com/.hidden/hidden.go
+
+-- $WORK/_origin/foo/_ok/main.go --
+package main
+
+func main() {}
+
+-- $WORK/_origin/foo/_sneaky/main.go --
+package main
+import _ "example.com/.hidden"
+
+func main() {}
+
+-- $WORK/_origin/.hidden/hidden.go --
+package hidden
diff --git a/src/cmd/go/testdata/script/get_tilde.txt b/src/cmd/go/testdata/script/get_tilde.txt
new file mode 100644
index 0000000000..08289ca405
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_tilde.txt
@@ -0,0 +1,21 @@
+# Paths containing windows short names should be rejected before attempting to fetch.
+! go get example.com/longna~1.dir/thing
+stderr 'trailing tilde and digits'
+! go get example.com/longna~1/thing
+stderr 'trailing tilde and digits'
+! go get example.com/~9999999/thing
+stderr 'trailing tilde and digits'
+
+# A path containing an element that is just a tilde, or a tilde followed by non-digits,
+# should attempt to resolve.
+! go get example.com/~glenda/notfound
+! stderr 'trailing tilde and digits'
+stderr 'unrecognized import path'
+
+! go get example.com/~glenda2/notfound
+! stderr 'trailing tilde and digits'
+stderr 'unrecognized import path'
+
+! go get example.com/~/notfound
+! stderr 'trailing tilde and digits'
+stderr 'unrecognized import path'
diff --git a/src/cmd/go/testdata/script/get_unicode.txt b/src/cmd/go/testdata/script/get_unicode.txt
new file mode 100644
index 0000000000..31edcdb9f6
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_unicode.txt
@@ -0,0 +1,37 @@
+[!exec:git] skip
+
+# Construct a repository that imports a non-ASCII path.
+cd $WORK/_origin/example.com/unicode
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git add unicode.go
+exec git commit -m 'add unicode.go'
+
+# Clone the repo into GOPATH so that 'go get -u' can find it.
+mkdir $GOPATH/src/example.com/unicode
+cd $GOPATH/src/example.com/unicode
+exec git clone $WORK/_origin/example.com/unicode .
+
+# Construct the imported repository.
+cd $WORK/_origin/example.com/испытание
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git add испытание.go
+exec git commit -m 'add испытание.go'
+
+# Clone that repo into GOPATH too.
+mkdir $GOPATH/src/example.com/испытание
+cd $GOPATH/src/example.com/испытание
+exec git clone $WORK/_origin/example.com/испытание .
+
+# Upgrading the importer should pull from the non-ASCII repo.
+cd $GOPATH
+go get -u example.com/unicode
+
+-- $WORK/_origin/example.com/unicode/unicode.go --
+package unicode
+import _ "example.com/испытание"
+-- $WORK/_origin/example.com/испытание/испытание.go --
+package испытание
diff --git a/src/cmd/go/testdata/script/mod_go_version.txt b/src/cmd/go/testdata/script/mod_go_version.txt
index f2de74cee8..37f173531b 100644
--- a/src/cmd/go/testdata/script/mod_go_version.txt
+++ b/src/cmd/go/testdata/script/mod_go_version.txt
@@ -3,9 +3,10 @@
env GO111MODULE=on
go list
-! go build
-stderr 'module requires Go 1.999'
+go build
go build sub.1
+go build subver.1
+! stderr 'module requires'
! go build badsub.1
stderr 'module requires Go 1.11111'
@@ -19,11 +20,13 @@ module m
go 1.999
require (
sub.1 v1.0.0
+ subver.1 v1.0.0
badsub.1 v1.0.0
versioned.1 v1.0.0
)
replace (
sub.1 => ./sub
+ subver.1 => ./subver
badsub.1 => ./badsub
versioned.1 v1.0.0 => ./versioned1
versioned.1 v1.1.0 => ./versioned2
@@ -39,12 +42,20 @@ go 1.11
-- sub/x.go --
package x
+-- subver/go.mod --
+module m
+go 1.11111
+
+-- subver/x.go --
+package x
+
-- badsub/go.mod --
module m
go 1.11111
-- badsub/x.go --
package x
+invalid syntax
-- versioned1/go.mod --
module versioned
@@ -59,3 +70,4 @@ go 1.99999
-- versioned2/x.go --
package x
+invalid syntax
diff --git a/src/cmd/go/testdata/script/run_wildcard.txt b/src/cmd/go/testdata/script/run_wildcard.txt
new file mode 100644
index 0000000000..cd401e00e6
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_wildcard.txt
@@ -0,0 +1,5 @@
+# Fix for https://github.com/golang/go/issues/28696:
+# go run x/... should not panic when directory x doesn't exist.
+
+! go run nonexistent/...
+stderr '^go run: no packages loaded from nonexistent/...$'
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 2329ca6379..eeb1f00057 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -983,6 +983,7 @@ func hostobjCopy() (paths []string) {
if err != nil {
Exitf("cannot reopen %s: %v", h.pn, err)
}
+ defer f.Close()
if _, err := f.Seek(h.off, 0); err != nil {
Exitf("cannot seek %s: %v", h.pn, err)
}
diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go
index a1646b9826..61107f86b8 100644
--- a/src/crypto/x509/cert_pool.go
+++ b/src/crypto/x509/cert_pool.go
@@ -65,32 +65,16 @@ func SystemCertPool() (*CertPool, error) {
return loadSystemRoots()
}
-// findVerifiedParents attempts to find certificates in s which have signed the
-// given certificate. If any candidates were rejected then errCert will be set
-// to one of them, arbitrarily, and err will contain the reason that it was
-// rejected.
-func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
+// findPotentialParents returns the indexes of certificates in s which might
+// have signed cert. The caller must not modify the returned slice.
+func (s *CertPool) findPotentialParents(cert *Certificate) []int {
if s == nil {
- return
+ return nil
}
- var candidates []int
-
if len(cert.AuthorityKeyId) > 0 {
- candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
- }
- if len(candidates) == 0 {
- candidates = s.byName[string(cert.RawIssuer)]
+ return s.bySubjectKeyId[string(cert.AuthorityKeyId)]
}
-
- for _, c := range candidates {
- if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
- parents = append(parents, c)
- } else {
- errCert = s.certs[c]
- }
- }
-
- return
+ return s.byName[string(cert.RawIssuer)]
}
func (s *CertPool) contains(cert *Certificate) bool {
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
index 5a5e6abaf1..122a7c6cbf 100644
--- a/src/crypto/x509/verify.go
+++ b/src/crypto/x509/verify.go
@@ -777,7 +777,7 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
if opts.Roots.contains(c) {
candidateChains = append(candidateChains, []*Certificate{c})
} else {
- if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil {
+ if candidateChains, err = c.buildChains(nil, []*Certificate{c}, nil, &opts); err != nil {
return nil, err
}
}
@@ -814,58 +814,74 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate
return n
}
-func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
- possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
-nextRoot:
- for _, rootNum := range possibleRoots {
- root := opts.Roots.certs[rootNum]
+// maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls
+// that an invocation of buildChains will (tranistively) make. Most chains are
+// less than 15 certificates long, so this leaves space for multiple chains and
+// for failed checks due to different intermediates having the same Subject.
+const maxChainSignatureChecks = 100
+func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) {
+ var (
+ hintErr error
+ hintCert *Certificate
+ )
+
+ considerCandidate := func(certType int, candidate *Certificate) {
for _, cert := range currentChain {
- if cert.Equal(root) {
- continue nextRoot
+ if cert.Equal(candidate) {
+ return
}
}
- err = root.isValid(rootCertificate, currentChain, opts)
- if err != nil {
- continue
+ if sigChecks == nil {
+ sigChecks = new(int)
+ }
+ *sigChecks++
+ if *sigChecks > maxChainSignatureChecks {
+ err = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
+ return
}
- chains = append(chains, appendToFreshChain(currentChain, root))
- }
- possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
-nextIntermediate:
- for _, intermediateNum := range possibleIntermediates {
- intermediate := opts.Intermediates.certs[intermediateNum]
- for _, cert := range currentChain {
- if cert.Equal(intermediate) {
- continue nextIntermediate
+ if err := c.CheckSignatureFrom(candidate); err != nil {
+ if hintErr == nil {
+ hintErr = err
+ hintCert = candidate
}
+ return
}
- err = intermediate.isValid(intermediateCertificate, currentChain, opts)
+
+ err = candidate.isValid(certType, currentChain, opts)
if err != nil {
- continue
+ return
}
- var childChains [][]*Certificate
- childChains, ok := cache[intermediateNum]
- if !ok {
- childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
- cache[intermediateNum] = childChains
+
+ switch certType {
+ case rootCertificate:
+ chains = append(chains, appendToFreshChain(currentChain, candidate))
+ case intermediateCertificate:
+ if cache == nil {
+ cache = make(map[*Certificate][][]*Certificate)
+ }
+ childChains, ok := cache[candidate]
+ if !ok {
+ childChains, err = candidate.buildChains(cache, appendToFreshChain(currentChain, candidate), sigChecks, opts)
+ cache[candidate] = childChains
+ }
+ chains = append(chains, childChains...)
}
- chains = append(chains, childChains...)
+ }
+
+ for _, rootNum := range opts.Roots.findPotentialParents(c) {
+ considerCandidate(rootCertificate, opts.Roots.certs[rootNum])
+ }
+ for _, intermediateNum := range opts.Intermediates.findPotentialParents(c) {
+ considerCandidate(intermediateCertificate, opts.Intermediates.certs[intermediateNum])
}
if len(chains) > 0 {
err = nil
}
-
if len(chains) == 0 && err == nil {
- hintErr := rootErr
- hintCert := failedRoot
- if hintErr == nil {
- hintErr = intermediateErr
- hintCert = failedIntermediate
- }
err = UnknownAuthorityError{c, hintErr, hintCert}
}
diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
index 0e24d3b5da..85f4703d4c 100644
--- a/src/crypto/x509/verify_test.go
+++ b/src/crypto/x509/verify_test.go
@@ -5,10 +5,15 @@
package x509
import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
"crypto/x509/pkix"
"encoding/pem"
"errors"
"fmt"
+ "math/big"
"runtime"
"strings"
"testing"
@@ -1889,3 +1894,117 @@ func TestValidHostname(t *testing.T) {
}
}
}
+
+func generateCert(cn string, isCA bool, issuer *Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) {
+ priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+ serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
+
+ template := &Certificate{
+ SerialNumber: serialNumber,
+ Subject: pkix.Name{CommonName: cn},
+ NotBefore: time.Now().Add(-1 * time.Hour),
+ NotAfter: time.Now().Add(24 * time.Hour),
+
+ KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature | KeyUsageCertSign,
+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ IsCA: isCA,
+ }
+ if issuer == nil {
+ issuer = template
+ issuerKey = priv
+ }
+
+ derBytes, err := CreateCertificate(rand.Reader, template, issuer, priv.Public(), issuerKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ cert, err := ParseCertificate(derBytes)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return cert, priv, nil
+}
+
+func TestPathologicalChain(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping generation of a long chain of certificates in short mode")
+ }
+
+ // Build a chain where all intermediates share the same subject, to hit the
+ // path building worst behavior.
+ roots, intermediates := NewCertPool(), NewCertPool()
+
+ parent, parentKey, err := generateCert("Root CA", true, nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ roots.AddCert(parent)
+
+ for i := 1; i < 100; i++ {
+ parent, parentKey, err = generateCert("Intermediate CA", true, parent, parentKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+ intermediates.AddCert(parent)
+ }
+
+ leaf, _, err := generateCert("Leaf", false, parent, parentKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ start := time.Now()
+ _, err = leaf.Verify(VerifyOptions{
+ Roots: roots,
+ Intermediates: intermediates,
+ })
+ t.Logf("verification took %v", time.Since(start))
+
+ if err == nil || !strings.Contains(err.Error(), "signature check attempts limit") {
+ t.Errorf("expected verification to fail with a signature checks limit error; got %v", err)
+ }
+}
+
+func TestLongChain(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping generation of a long chain of certificates in short mode")
+ }
+
+ roots, intermediates := NewCertPool(), NewCertPool()
+
+ parent, parentKey, err := generateCert("Root CA", true, nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ roots.AddCert(parent)
+
+ for i := 1; i < 15; i++ {
+ name := fmt.Sprintf("Intermediate CA #%d", i)
+ parent, parentKey, err = generateCert(name, true, parent, parentKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+ intermediates.AddCert(parent)
+ }
+
+ leaf, _, err := generateCert("Leaf", false, parent, parentKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ start := time.Now()
+ if _, err := leaf.Verify(VerifyOptions{
+ Roots: roots,
+ Intermediates: intermediates,
+ }); err != nil {
+ t.Error(err)
+ }
+ t.Logf("verification took %v", time.Since(start))
+}
diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go
index 5cbaba187b..6646711e7f 100644
--- a/src/go/types/resolver.go
+++ b/src/go/types/resolver.go
@@ -538,7 +538,25 @@ func (check *Checker) packageObjects() {
// pre-allocate space for type declaration paths so that the underlying array is reused
typePath := make([]*TypeName, 0, 8)
+ // We process non-alias declarations first, in order to avoid situations where
+ // the type of an alias declaration is needed before it is available. In general
+ // this is still not enough, as it is possible to create sufficiently convoluted
+ // recursive type definitions that will cause a type alias to be needed before it
+ // is available (see issue #25838 for examples).
+ // As an aside, the cmd/compiler suffers from the same problem (#25838).
+ var aliasList []*TypeName
+ // phase 1
for _, obj := range objList {
+ // If we have a type alias, collect it for the 2nd phase.
+ if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].alias {
+ aliasList = append(aliasList, tname)
+ continue
+ }
+
+ check.objDecl(obj, nil, typePath)
+ }
+ // phase 2
+ for _, obj := range aliasList {
check.objDecl(obj, nil, typePath)
}
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index 229d203099..ce6c60624f 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -176,6 +176,7 @@ func TestStdFixed(t *testing.T) {
"issue22200b.go", // go/types does not have constraints on stack size
"issue25507.go", // go/types does not have constraints on stack size
"issue20780.go", // go/types does not have constraints on stack size
+ "issue27232.go", // go/types has a bug with alias type (issue #28576)
)
}
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
index 12cf65f109..2cd2b86df2 100644
--- a/src/net/http/h2_bundle.go
+++ b/src/net/http/h2_bundle.go
@@ -7705,6 +7705,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
default:
}
if err != nil {
+ cc.forgetStreamID(cs.ID)
return nil, cs.getStartedWrite(), err
}
bodyWritten = true
@@ -7826,6 +7827,7 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos
sawEOF = true
err = nil
} else if err != nil {
+ cc.writeStreamReset(cs.ID, http2ErrCodeCancel, err)
return err
}
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
index c85033f4bc..64a80ad1fd 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -130,12 +130,19 @@ func cgocall(fn, arg unsafe.Pointer) int32 {
mp.incgo = true
errno := asmcgocall(fn, arg)
- // Call endcgo before exitsyscall because exitsyscall may
+ // Update accounting before exitsyscall because exitsyscall may
// reschedule us on to a different M.
- endcgo(mp)
+ mp.incgo = false
+ mp.ncgo--
exitsyscall()
+ // Note that raceacquire must be called only after exitsyscall has
+ // wired this M to a P.
+ if raceenabled {
+ raceacquire(unsafe.Pointer(&racecgosync))
+ }
+
// From the garbage collector's perspective, time can move
// backwards in the sequence above. If there's a callback into
// Go code, GC will see this function at the call to
@@ -153,16 +160,6 @@ func cgocall(fn, arg unsafe.Pointer) int32 {
return errno
}
-//go:nosplit
-func endcgo(mp *m) {
- mp.incgo = false
- mp.ncgo--
-
- if raceenabled {
- raceacquire(unsafe.Pointer(&racecgosync))
- }
-}
-
// Call from C back to Go.
//go:nosplit
func cgocallbackg(ctxt uintptr) {
@@ -346,13 +343,14 @@ func unwindm(restore *bool) {
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
}
- // Call endcgo to do the accounting that cgocall will not have a
- // chance to do during an unwind.
+ // Do the accounting that cgocall will not have a chance to do
+ // during an unwind.
//
// In the case where a Go call originates from C, ncgo is 0
// and there is no matching cgocall to end.
if mp.ncgo > 0 {
- endcgo(mp)
+ mp.incgo = false
+ mp.ncgo--
}
releasem(mp)
diff --git a/src/runtime/os_linux_arm64.go b/src/runtime/os_linux_arm64.go
index 28a0319f10..59f3df47fe 100644
--- a/src/runtime/os_linux_arm64.go
+++ b/src/runtime/os_linux_arm64.go
@@ -29,7 +29,17 @@ func archauxv(tag, val uintptr) {
randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 |
uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24
case _AT_HWCAP:
- cpu_hwcap = uint(val)
+ // arm64 doesn't have a 'cpuid' instruction equivalent and relies on
+ // HWCAP/HWCAP2 bits for hardware capabilities.
+ hwcap := uint(val)
+ if GOOS == "android" {
+ // The Samsung S9+ kernel reports support for atomics, but not all cores
+ // actually support them, resulting in SIGILL. See issue #28431.
+ // TODO(elias.naur): Only disable the optimization on bad chipsets.
+ const hwcap_ATOMICS = 1 << 8
+ hwcap &= ^uint(hwcap_ATOMICS)
+ }
+ cpu_hwcap = hwcap
case _AT_HWCAP2:
cpu_hwcap2 = uint(val)
}
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
index c7bfc0434b..7bb82038ab 100644
--- a/src/runtime/stack.go
+++ b/src/runtime/stack.go
@@ -1221,7 +1221,14 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args
// Arguments.
if frame.arglen > 0 {
if frame.argmap != nil {
+ // argmap is set when the function is reflect.makeFuncStub or reflect.methodValueCall.
+ // In this case, arglen specifies how much of the args section is actually live.
+ // (It could be either all the args + results, or just the args.)
args = *frame.argmap
+ n := int32(frame.arglen / sys.PtrSize)
+ if n < args.n {
+ args.n = n // Don't use more of the arguments than arglen.
+ }
} else {
stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
if stackmap == nil || stackmap.n <= 0 {
diff --git a/test/fixedbugs/issue18640.go b/test/fixedbugs/issue18640.go
index 60abd31f76..091bbe596b 100644
--- a/test/fixedbugs/issue18640.go
+++ b/test/fixedbugs/issue18640.go
@@ -20,8 +20,7 @@ type (
d = c
)
-// The compiler reports an incorrect (non-alias related)
-// type cycle here (via dowith()). Disabled for now.
+// The compiler cannot handle these cases. Disabled for now.
// See issue #25838.
/*
type (
@@ -32,7 +31,6 @@ type (
i = j
j = e
)
-*/
type (
a1 struct{ *b1 }
@@ -45,3 +43,4 @@ type (
b2 = c2
c2 struct{ *b2 }
)
+*/
diff --git a/test/fixedbugs/issue23823.go b/test/fixedbugs/issue23823.go
index 2f802d0988..9297966cbd 100644
--- a/test/fixedbugs/issue23823.go
+++ b/test/fixedbugs/issue23823.go
@@ -1,4 +1,4 @@
-// errorcheck
+// compile
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -6,10 +6,14 @@
package p
+// The compiler cannot handle this. Disabled for now.
+// See issue #25838.
+/*
type I1 = interface {
I2
}
-type I2 interface { // ERROR "invalid recursive type"
+type I2 interface {
I1
}
+*/
diff --git a/test/fixedbugs/issue24939.go b/test/fixedbugs/issue24939.go
index 26530e95b2..0ae6f2b9f2 100644
--- a/test/fixedbugs/issue24939.go
+++ b/test/fixedbugs/issue24939.go
@@ -15,7 +15,9 @@ type M interface {
}
type P = interface {
- I() M
+ // The compiler cannot handle this case. Disabled for now.
+ // See issue #25838.
+ // I() M
}
func main() {}
diff --git a/test/fixedbugs/issue27232.go b/test/fixedbugs/issue27232.go
new file mode 100644
index 0000000000..3a1cc87e4c
--- /dev/null
+++ b/test/fixedbugs/issue27232.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2018 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 p
+
+type F = func(T)
+
+type T interface {
+ m(F)
+}
+
+type t struct{}
+
+func (t) m(F) {}
+
+var _ T = &t{}
diff --git a/test/fixedbugs/issue27267.go b/test/fixedbugs/issue27267.go
new file mode 100644
index 0000000000..ebae44f48f
--- /dev/null
+++ b/test/fixedbugs/issue27267.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2018 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 p
+
+// 1st test case from issue
+type F = func(E) // compiles if not type alias or moved below E struct
+type E struct {
+ f F
+}
+
+var x = E{func(E) {}}
+
+// 2nd test case from issue
+type P = *S
+type S struct {
+ p P
+}
diff --git a/test/fixedbugs/issue27695c.go b/test/fixedbugs/issue27695c.go
new file mode 100644
index 0000000000..948191cc96
--- /dev/null
+++ b/test/fixedbugs/issue27695c.go
@@ -0,0 +1,65 @@
+// run
+
+// Copyright 2018 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.
+
+// Make sure return values aren't scanned until they
+// are initialized, when calling functions and methods
+// via reflect.
+
+package main
+
+import (
+ "io"
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+var badPtr uintptr
+
+var sink []byte
+
+func init() {
+ // Allocate large enough to use largeAlloc.
+ b := make([]byte, 1<<16-1)
+ sink = b // force heap allocation
+ // Any space between the object and the end of page is invalid to point to.
+ badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
+}
+
+func f(d func(error) error) error {
+ // Initialize callee args section with a bad pointer.
+ g(badPtr, badPtr, badPtr, badPtr)
+
+ // Then call a function which returns a pointer.
+ // That return slot starts out holding a bad pointer.
+ return d(io.EOF)
+}
+
+//go:noinline
+func g(x, y, z, w uintptr) {
+}
+
+type T struct {
+}
+
+func (t *T) Foo(e error) error {
+ runtime.GC()
+ return e
+}
+
+func main() {
+ // Functions
+ d := reflect.MakeFunc(reflect.TypeOf(func(e error) error { return e }),
+ func(args []reflect.Value) []reflect.Value {
+ runtime.GC()
+ return args
+ }).Interface().(func(error) error)
+ f(d)
+
+ // Methods
+ x := reflect.ValueOf(&T{}).Method(0).Interface().(func(error) error)
+ f(x)
+}
diff --git a/test/fixedbugs/issue28616.go b/test/fixedbugs/issue28616.go
new file mode 100644
index 0000000000..f1ba974797
--- /dev/null
+++ b/test/fixedbugs/issue28616.go
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2018 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.
+
+// Make sure we don't dead code eliminate a label.
+
+package p
+
+var i int
+
+func f() {
+
+ if true {
+
+ if i == 1 {
+ goto label
+ }
+
+ return
+ }
+
+label:
+}
diff --git a/test/fixedbugs/issue28688.go b/test/fixedbugs/issue28688.go
new file mode 100644
index 0000000000..0d2000e149
--- /dev/null
+++ b/test/fixedbugs/issue28688.go
@@ -0,0 +1,31 @@
+// run -gcflags=-d=softfloat
+
+// Copyright 2018 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 (
+ "fmt"
+)
+
+// When using soft-float, OMUL might be rewritten to function
+// call so we should ensure it was evaluated first. Stack frame
+// setup for "test" function call should happen after call to runtime.fmul32
+
+var x int32 = 1
+
+func main() {
+ var y float32 = 1.0
+ test(x, y*y)
+}
+
+//go:noinline
+func test(id int32, a float32) {
+
+ if id != x {
+ fmt.Printf("got: %d, want: %d\n", id, x)
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue28797.go b/test/fixedbugs/issue28797.go
new file mode 100644
index 0000000000..480c1059b8
--- /dev/null
+++ b/test/fixedbugs/issue28797.go
@@ -0,0 +1,53 @@
+// run
+
+// Copyright 2018 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 (
+ "fmt"
+)
+
+// test expects f to panic, but not to run out of memory,
+// which is a non-panic fatal error. OOM results from failure
+// to properly check negative limit.
+func test(f func()) {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("panic wasn't recoverable")
+ }
+ }()
+ f()
+}
+
+//go:noinline
+func id(x int) int {
+ return x
+}
+
+func main() {
+ test(foo)
+ test(bar)
+}
+
+func foo() {
+ b := make([]byte, 0)
+ b = append(b, 1)
+ id(len(b))
+ id(len(b) - 2)
+ s := string(b[1 : len(b)-2])
+ fmt.Println(s)
+}
+
+func bar() {
+ b := make([]byte, 1)
+ b = append(b, 1)
+ i := id(-1)
+ if i < len(b) { // establish value is not too large.
+ s := string(b[1:i]) // should check for negative also.
+ fmt.Println(s)
+ }
+}
diff --git a/test/loopbce.go b/test/loopbce.go
index b4bf797497..81f2524e95 100644
--- a/test/loopbce.go
+++ b/test/loopbce.go
@@ -6,7 +6,7 @@ package main
func f0a(a []int) int {
x := 0
for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- x += a[i] // ERROR "Proved IsInBounds$"
+ x += a[i] // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -14,7 +14,7 @@ func f0a(a []int) int {
func f0b(a []int) int {
x := 0
for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- b := a[i:] // ERROR "Proved IsSliceInBounds$"
+ b := a[i:] // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
x += b[0]
}
return x
@@ -23,7 +23,7 @@ func f0b(a []int) int {
func f0c(a []int) int {
x := 0
for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- b := a[:i+1] // ERROR "Proved IsSliceInBounds$"
+ b := a[:i+1] // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
x += b[0]
}
return x
@@ -40,7 +40,7 @@ func f1(a []int) int {
func f2(a []int) int {
x := 0
for i := 1; i < len(a); i++ { // ERROR "Induction variable: limits \[1,\?\), increment 1$"
- x += a[i] // ERROR "Proved IsInBounds$"
+ x += a[i] // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -48,7 +48,7 @@ func f2(a []int) int {
func f4(a [10]int) int {
x := 0
for i := 0; i < len(a); i += 2 { // ERROR "Induction variable: limits \[0,10\), increment 2$"
- x += a[i] // ERROR "Proved IsInBounds$"
+ x += a[i] // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -63,7 +63,7 @@ func f5(a [10]int) int {
func f6(a []int) {
for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- b := a[0:i] // ERROR "Proved IsSliceInBounds$"
+ b := a[0:i] // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$" "(\([0-9]+\) )?Proved Geq64$"
f6(b)
}
}
@@ -71,7 +71,7 @@ func f6(a []int) {
func g0a(a string) int {
x := 0
for i := 0; i < len(a); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- x += int(a[i]) // ERROR "Proved IsInBounds$"
+ x += int(a[i]) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -79,7 +79,7 @@ func g0a(a string) int {
func g0b(a string) int {
x := 0
for i := 0; len(a) > i; i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- x += int(a[i]) // ERROR "Proved IsInBounds$"
+ x += int(a[i]) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -87,7 +87,7 @@ func g0b(a string) int {
func g0c(a string) int {
x := 0
for i := len(a); i > 0; i-- { // ERROR "Induction variable: limits \(0,\?\], increment 1$"
- x += int(a[i-1]) // ERROR "Proved IsInBounds$"
+ x += int(a[i-1]) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -95,7 +95,7 @@ func g0c(a string) int {
func g0d(a string) int {
x := 0
for i := len(a); 0 < i; i-- { // ERROR "Induction variable: limits \(0,\?\], increment 1$"
- x += int(a[i-1]) // ERROR "Proved IsInBounds$"
+ x += int(a[i-1]) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -103,7 +103,7 @@ func g0d(a string) int {
func g0e(a string) int {
x := 0
for i := len(a) - 1; i >= 0; i-- { // ERROR "Induction variable: limits \[0,\?\], increment 1$"
- x += int(a[i]) // ERROR "Proved IsInBounds$"
+ x += int(a[i]) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -111,7 +111,7 @@ func g0e(a string) int {
func g0f(a string) int {
x := 0
for i := len(a) - 1; 0 <= i; i-- { // ERROR "Induction variable: limits \[0,\?\], increment 1$"
- x += int(a[i]) // ERROR "Proved IsInBounds$"
+ x += int(a[i]) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -120,7 +120,7 @@ func g1() int {
a := "evenlength"
x := 0
for i := 0; i < len(a); i += 2 { // ERROR "Induction variable: limits \[0,10\), increment 2$"
- x += int(a[i]) // ERROR "Proved IsInBounds$"
+ x += int(a[i]) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return x
}
@@ -130,7 +130,7 @@ func g2() int {
x := 0
for i := 0; i < len(a); i += 2 { // ERROR "Induction variable: limits \[0,10\), increment 2$"
j := i
- if a[i] == 'e' { // ERROR "Proved IsInBounds$"
+ if a[i] == 'e' { // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
j = j + 1
}
x += int(a[j])
@@ -141,27 +141,27 @@ func g2() int {
func g3a() {
a := "this string has length 25"
for i := 0; i < len(a); i += 5 { // ERROR "Induction variable: limits \[0,25\), increment 5$"
- useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ useString(a[i:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useString(a[:i+3])
}
}
func g3b(a string) {
for i := 0; i < len(a); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- useString(a[i+1:]) // ERROR "Proved IsSliceInBounds$"
+ useString(a[i+1:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
}
}
func g3c(a string) {
for i := 0; i < len(a); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- useString(a[:i+1]) // ERROR "Proved IsSliceInBounds$"
+ useString(a[:i+1]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
}
}
func h1(a []byte) {
c := a[:128]
for i := range c { // ERROR "Induction variable: limits \[0,128\), increment 1$"
- c[i] = byte(i) // ERROR "Proved IsInBounds$"
+ c[i] = byte(i) // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
}
@@ -174,11 +174,11 @@ func h2(a []byte) {
func k0(a [100]int) [100]int {
for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
a[i-11] = i
- a[i-10] = i // ERROR "Proved IsInBounds$"
- a[i-5] = i // ERROR "Proved IsInBounds$"
- a[i] = i // ERROR "Proved IsInBounds$"
- a[i+5] = i // ERROR "Proved IsInBounds$"
- a[i+10] = i // ERROR "Proved IsInBounds$"
+ a[i-10] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
+ a[i-5] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
+ a[i] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
+ a[i+5] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
+ a[i+10] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
a[i+11] = i
}
return a
@@ -186,13 +186,13 @@ func k0(a [100]int) [100]int {
func k1(a [100]int) [100]int {
for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
- useSlice(a[:i-11])
- useSlice(a[:i-10]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[:i-5]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[:i]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[:i+5]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[:i+10]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[:i+11]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i-11]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[:i-10]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[:i-5]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[:i]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$" "(\([0-9]+\) )?Proved Geq64$"
+ useSlice(a[:i+5]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[:i+10]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[:i+11]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i+12])
}
@@ -202,12 +202,12 @@ func k1(a [100]int) [100]int {
func k2(a [100]int) [100]int {
for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
useSlice(a[i-11:])
- useSlice(a[i-10:]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[i-5:]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[i:]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[i+5:]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[i+10:]) // ERROR "Proved IsSliceInBounds$"
- useSlice(a[i+11:]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[i-10:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[i-5:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[i:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[i+5:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[i+10:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[i+11:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[i+12:])
}
return a
@@ -216,7 +216,7 @@ func k2(a [100]int) [100]int {
func k3(a [100]int) [100]int {
for i := -10; i < 90; i++ { // ERROR "Induction variable: limits \[-10,90\), increment 1$"
a[i+9] = i
- a[i+10] = i // ERROR "Proved IsInBounds$"
+ a[i+10] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
a[i+11] = i
}
return a
@@ -225,7 +225,7 @@ func k3(a [100]int) [100]int {
func k3neg(a [100]int) [100]int {
for i := 89; i > -11; i-- { // ERROR "Induction variable: limits \(-11,89\], increment 1$"
a[i+9] = i
- a[i+10] = i // ERROR "Proved IsInBounds$"
+ a[i+10] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
a[i+11] = i
}
return a
@@ -234,7 +234,7 @@ func k3neg(a [100]int) [100]int {
func k3neg2(a [100]int) [100]int {
for i := 89; i >= -10; i-- { // ERROR "Induction variable: limits \[-10,89\], increment 1$"
a[i+9] = i
- a[i+10] = i // ERROR "Proved IsInBounds$"
+ a[i+10] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
a[i+11] = i
}
return a
@@ -243,16 +243,16 @@ func k3neg2(a [100]int) [100]int {
func k4(a [100]int) [100]int {
min := (-1) << 63
for i := min; i < min+50; i++ { // ERROR "Induction variable: limits \[-9223372036854775808,-9223372036854775758\), increment 1$"
- a[i-min] = i // ERROR "Proved IsInBounds$"
+ a[i-min] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return a
}
func k5(a [100]int) [100]int {
max := (1 << 63) - 1
- for i := max - 50; i < max; i++ { // ERROR "Induction variable: limits \[9223372036854775757,9223372036854775807\), increment 1"
- a[i-max+50] = i // ERROR "Proved IsInBounds$"
- a[i-(max-70)] = i // ERROR "Proved IsInBounds$"
+ for i := max - 50; i < max; i++ { // ERROR "Induction variable: limits \[9223372036854775757,9223372036854775807\), increment 1$"
+ a[i-max+50] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
+ a[i-(max-70)] = i // ERROR "(\([0-9]+\) )?Proved IsInBounds$"
}
return a
}
@@ -275,17 +275,17 @@ func nobce1() {
func nobce2(a string) {
for i := int64(0); i < int64(len(a)); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ useString(a[i:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
}
for i := int64(0); i < int64(len(a))-31337; i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ useString(a[i:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
}
for i := int64(0); i < int64(len(a))+int64(-1<<63); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ useString(a[i:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
}
j := int64(len(a)) - 123
for i := int64(0); i < j+123+int64(-1<<63); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ useString(a[i:]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
}
for i := int64(0); i < j+122+int64(-1<<63); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
// len(a)-123+122+MinInt overflows when len(a) == 0, so a bound check is needed here
diff --git a/test/prove.go b/test/prove.go
index 79256893b3..0de6bd63b4 100644
--- a/test/prove.go
+++ b/test/prove.go
@@ -62,7 +62,7 @@ func f1c(a []int, i int64) int {
}
func f2(a []int) int {
- for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1"
+ for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
a[i+1] = i
a[i+1] = i // ERROR "Proved IsInBounds$"
}
@@ -269,7 +269,7 @@ func f11b(a []int, i int) {
func f11c(a []int, i int) {
useSlice(a[:i])
- useSlice(a[:i]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i]) // ERROR "Proved Geq64$" "Proved IsSliceInBounds$"
}
func f11d(a []int, i int) {
@@ -464,12 +464,12 @@ func f16(s []int) []int {
}
func f17(b []int) {
- for i := 0; i < len(b); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1"
+ for i := 0; i < len(b); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
// This tests for i <= cap, which we can only prove
// using the derived relation between len and cap.
// This depends on finding the contradiction, since we
// don't query this condition directly.
- useSlice(b[:i]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(b[:i]) // ERROR "Proved Geq64$" "Proved IsSliceInBounds$"
}
}
@@ -579,18 +579,18 @@ func fence4(x, y int64) {
func trans1(x, y int64) {
if x > 5 {
if y > x {
- if y > 2 { // ERROR "Proved Greater64"
+ if y > 2 { // ERROR "Proved Greater64$"
return
}
} else if y == x {
- if y > 5 { // ERROR "Proved Greater64"
+ if y > 5 { // ERROR "Proved Greater64$"
return
}
}
}
if x >= 10 {
if y > x {
- if y > 10 { // ERROR "Proved Greater64"
+ if y > 10 { // ERROR "Proved Greater64$"
return
}
}
@@ -624,7 +624,7 @@ func natcmp(x, y []uint) (r int) {
}
i := m - 1
- for i > 0 && // ERROR "Induction variable: limits \(0,\?\], increment 1"
+ for i > 0 && // ERROR "Induction variable: limits \(0,\?\], increment 1$"
x[i] == // ERROR "Proved IsInBounds$"
y[i] { // ERROR "Proved IsInBounds$"
i--
@@ -686,7 +686,7 @@ func range2(b [][32]int) {
if i < len(b) { // ERROR "Proved Less64$"
println("x")
}
- if i >= 0 { // ERROR "Proved Geq64"
+ if i >= 0 { // ERROR "Proved Geq64$"
println("x")
}
}
diff --git a/test/run.go b/test/run.go
index 99ef79feb1..5a81da8d67 100644
--- a/test/run.go
+++ b/test/run.go
@@ -1180,7 +1180,7 @@ func (t *test) updateErrors(out, file string) {
msg := errStr[colon2+2:]
msg = strings.Replace(msg, file, base, -1) // normalize file mentions in error itself
msg = strings.TrimLeft(msg, " \t")
- for _, r := range []string{`\`, `*`, `+`, `[`, `]`, `(`, `)`} {
+ for _, r := range []string{`\`, `*`, `+`, `?`, `[`, `]`, `(`, `)`} {
msg = strings.Replace(msg, r, `\`+r, -1)
}
msg = strings.Replace(msg, `"`, `.`, -1)