From dc725bfb3c3f29c7395e088d25ef6bf8dba8f129 Mon Sep 17 00:00:00 2001
From: KimMachineGun
Date: Mon, 8 Feb 2021 23:27:52 +0000
Subject: [PATCH 01/47] doc/go1.16: mention new vet check for asn1.Unmarshal
This vet check was added in CL 243397.
For #40700.
Change-Id: Ibff6df9395d37bb2b84a791443578009f23af4fb
GitHub-Last-Rev: e47c38f6309f31a6de48d4ffc82078d7ad45b171
GitHub-Pull-Request: golang/go#44147
Reviewed-on: https://go-review.googlesource.com/c/go/+/290330
Trust: Ian Lance Taylor
Reviewed-by: Dmitri Shuralyov
---
doc/go1.16.html | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/doc/go1.16.html b/doc/go1.16.html
index 878bf0d029..f6f72c3882 100644
--- a/doc/go1.16.html
+++ b/doc/go1.16.html
@@ -378,6 +378,16 @@ func TestFoo(t *testing.T) {
fixes.
+New warning for asn1.Unmarshal
+
+
+ The vet tool now warns about incorrectly passing a non-pointer or nil argument to
+ asn1.Unmarshal.
+ This is like the existing checks for
+ encoding/json.Unmarshal
+ and encoding/xml.Unmarshal.
+
+
Runtime
From cea4e21b525ad6b465f62741680eaa0a44e9cc3e Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Mon, 8 Feb 2021 16:32:39 -0800
Subject: [PATCH 02/47] io/fs: backslash is always a glob meta character
Fixes #44171
Change-Id: I2d3437a2f5b9fa0358e4664e1a8eacebed975eed
Reviewed-on: https://go-review.googlesource.com/c/go/+/290512
Trust: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Go Bot
Reviewed-by: Rob Pike
Reviewed-by: Russ Cox
---
src/io/fs/glob.go | 5 ++---
src/io/fs/glob_test.go | 3 ++-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/io/fs/glob.go b/src/io/fs/glob.go
index 549f217542..45d9cb61b9 100644
--- a/src/io/fs/glob.go
+++ b/src/io/fs/glob.go
@@ -6,7 +6,6 @@ package fs
import (
"path"
- "runtime"
)
// A GlobFS is a file system with a Glob method.
@@ -111,8 +110,8 @@ func glob(fs FS, dir, pattern string, matches []string) (m []string, e error) {
// recognized by path.Match.
func hasMeta(path string) bool {
for i := 0; i < len(path); i++ {
- c := path[i]
- if c == '*' || c == '?' || c == '[' || runtime.GOOS == "windows" && c == '\\' {
+ switch path[i] {
+ case '*', '?', '[', '\\':
return true
}
}
diff --git a/src/io/fs/glob_test.go b/src/io/fs/glob_test.go
index f0d791fab5..f19bebed77 100644
--- a/src/io/fs/glob_test.go
+++ b/src/io/fs/glob_test.go
@@ -17,6 +17,7 @@ var globTests = []struct {
}{
{os.DirFS("."), "glob.go", "glob.go"},
{os.DirFS("."), "gl?b.go", "glob.go"},
+ {os.DirFS("."), `gl\ob.go`, "glob.go"},
{os.DirFS("."), "*", "glob.go"},
{os.DirFS(".."), "*/glob.go", "fs/glob.go"},
}
@@ -32,7 +33,7 @@ func TestGlob(t *testing.T) {
t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result)
}
}
- for _, pattern := range []string{"no_match", "../*/no_match"} {
+ for _, pattern := range []string{"no_match", "../*/no_match", `\*`} {
matches, err := Glob(os.DirFS("."), pattern)
if err != nil {
t.Errorf("Glob error for %q: %s", pattern, err)
From c9d6f45fec19a9cb66ddd89d61bfa982f5bf4afe Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Sun, 7 Feb 2021 15:25:39 -0800
Subject: [PATCH 03/47] runtime/metrics: fix a couple of documentation typpos
Fixes #44150
Change-Id: Ibe5bfba01491dd8c2f0696fab40a1673230d76e9
Reviewed-on: https://go-review.googlesource.com/c/go/+/290349
Trust: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Go Bot
Reviewed-by: Dmitri Shuralyov
Reviewed-by: Michael Knyszek
---
src/runtime/metrics/doc.go | 7 ++++---
src/runtime/metrics/sample.go | 6 +++---
src/runtime/metrics/value.go | 2 +-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go
index 021a0bddca..5da050f973 100644
--- a/src/runtime/metrics/doc.go
+++ b/src/runtime/metrics/doc.go
@@ -16,13 +16,14 @@ Interface
Metrics are designated by a string key, rather than, for example, a field name in
a struct. The full list of supported metrics is always available in the slice of
Descriptions returned by All. Each Description also includes useful information
-about the metric, such as how to display it (e.g. gauge vs. counter) and how difficult
-or disruptive it is to obtain it (e.g. do you need to stop the world?).
+about the metric, such as how to display it (for example, gauge vs. counter)
+and how difficult or disruptive it is to obtain it (for example, do you need to
+stop the world?).
Thus, users of this API are encouraged to sample supported metrics defined by the
slice returned by All to remain compatible across Go versions. Of course, situations
arise where reading specific metrics is critical. For these cases, users are
-encouranged to use build tags, and although metrics may be deprecated and removed,
+encouraged to use build tags, and although metrics may be deprecated and removed,
users should consider this to be an exceptional and rare event, coinciding with a
very large change in a particular Go implementation.
diff --git a/src/runtime/metrics/sample.go b/src/runtime/metrics/sample.go
index 35534dd70d..b3933e266e 100644
--- a/src/runtime/metrics/sample.go
+++ b/src/runtime/metrics/sample.go
@@ -32,9 +32,9 @@ func runtime_readMetrics(unsafe.Pointer, int, int)
//
// Note that re-use has some caveats. Notably, Values should not be read or
// manipulated while a Read with that value is outstanding; that is a data race.
-// This property includes pointer-typed Values (e.g. Float64Histogram) whose
-// underlying storage will be reused by Read when possible. To safely use such
-// values in a concurrent setting, all data must be deep-copied.
+// This property includes pointer-typed Values (for example, Float64Histogram)
+// whose underlying storage will be reused by Read when possible. To safely use
+// such values in a concurrent setting, all data must be deep-copied.
//
// It is safe to execute multiple Read calls concurrently, but their arguments
// must share no underlying memory. When in doubt, create a new []Sample from
diff --git a/src/runtime/metrics/value.go b/src/runtime/metrics/value.go
index 61e8a192a3..ed9a33d87c 100644
--- a/src/runtime/metrics/value.go
+++ b/src/runtime/metrics/value.go
@@ -33,7 +33,7 @@ type Value struct {
pointer unsafe.Pointer // contains non-scalar values.
}
-// Kind returns the a tag representing the kind of value this is.
+// Kind returns the tag representing the kind of value this is.
func (v Value) Kind() ValueKind {
return v.kind
}
From 11d15c171bd25337c1dde25a0f7ce4892cb894bb Mon Sep 17 00:00:00 2001
From: Rob Findley
Date: Thu, 4 Feb 2021 12:03:53 -0500
Subject: [PATCH 04/47] [dev.regabi] go/types: convert untyped arguments to
delete
This is a port of CL 285059 to go/types. The error assertion is updated
to match go/types error for assignment, which has been improved.
Change-Id: Icdd2751edea0abef7c84feadcbf9265d71239ade
Reviewed-on: https://go-review.googlesource.com/c/go/+/289716
Run-TryBot: Robert Findley
TryBot-Result: Go Bot
Trust: Robert Findley
Reviewed-by: Robert Griesemer
---
src/go/types/builtins.go | 4 ++--
src/go/types/testdata/builtins.src | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go
index fd35f78676..078ed4488d 100644
--- a/src/go/types/builtins.go
+++ b/src/go/types/builtins.go
@@ -353,8 +353,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
return
}
- if ok, code := x.assignableTo(check, m.key, nil); !ok {
- check.invalidArg(x, code, "%s is not assignable to %s", x, m.key)
+ check.assignment(x, m.key, "argument to delete")
+ if x.mode == invalid {
return
}
diff --git a/src/go/types/testdata/builtins.src b/src/go/types/testdata/builtins.src
index 98830eb08c..a7613adc35 100644
--- a/src/go/types/testdata/builtins.src
+++ b/src/go/types/testdata/builtins.src
@@ -283,7 +283,7 @@ func delete1() {
delete() // ERROR not enough arguments
delete(1) // ERROR not enough arguments
delete(1, 2, 3) // ERROR too many arguments
- delete(m, 0 /* ERROR not assignable */)
+ delete(m, 0 /* ERROR cannot use */)
delete(m, s)
_ = delete /* ERROR used as value */ (m, s)
From 813958f13cee9b2e7587f173e7a5e6cc9ff51850 Mon Sep 17 00:00:00 2001
From: Rob Findley
Date: Thu, 4 Feb 2021 12:10:02 -0500
Subject: [PATCH 05/47] [dev.regabi] go/types: factor out sorting of methods
This is a port of CL 285993 to go/types.
Change-Id: I7560cf1176fea5de2c54786a086e547c73294a60
Reviewed-on: https://go-review.googlesource.com/c/go/+/289717
Trust: Robert Findley
Trust: Robert Griesemer
Run-TryBot: Robert Findley
TryBot-Result: Go Bot
Reviewed-by: Robert Griesemer
---
src/go/types/predicates.go | 6 ++----
src/go/types/type.go | 8 +++-----
src/go/types/typexpr.go | 21 +++++++++++++++++++--
3 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go
index 148edbfb76..954a7ca987 100644
--- a/src/go/types/predicates.go
+++ b/src/go/types/predicates.go
@@ -6,8 +6,6 @@
package types
-import "sort"
-
func isNamed(typ Type) bool {
if _, ok := typ.(*Basic); ok {
return ok
@@ -273,8 +271,8 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
p = p.prev
}
if debug {
- assert(sort.IsSorted(byUniqueMethodName(a)))
- assert(sort.IsSorted(byUniqueMethodName(b)))
+ assertSortedMethods(a)
+ assertSortedMethods(b)
}
for i, f := range a {
g := b[i]
diff --git a/src/go/types/type.go b/src/go/types/type.go
index 087cda429d..66e194e967 100644
--- a/src/go/types/type.go
+++ b/src/go/types/type.go
@@ -4,8 +4,6 @@
package types
-import "sort"
-
// A Type represents a type of Go.
// All types implement the Type interface.
type Type interface {
@@ -301,8 +299,8 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
}
// sort for API stability
- sort.Sort(byUniqueMethodName(methods))
- sort.Stable(byUniqueTypeName(embeddeds))
+ sortMethods(methods)
+ sortTypes(embeddeds)
typ.methods = methods
typ.embeddeds = embeddeds
@@ -396,7 +394,7 @@ func (t *Interface) Complete() *Interface {
}
if methods != nil {
- sort.Sort(byUniqueMethodName(methods))
+ sortMethods(methods)
t.allMethods = methods
}
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 2b398010f4..311a970051 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -518,8 +518,8 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
}
// sort for API stability
- sort.Sort(byUniqueMethodName(ityp.methods))
- sort.Stable(byUniqueTypeName(ityp.embeddeds))
+ sortMethods(ityp.methods)
+ sortTypes(ityp.embeddeds)
check.later(func() { check.completeInterface(ityp) })
}
@@ -613,6 +613,10 @@ func (check *Checker) completeInterface(ityp *Interface) {
}
}
+func sortTypes(list []Type) {
+ sort.Stable(byUniqueTypeName(list))
+}
+
// byUniqueTypeName named type lists can be sorted by their unique type names.
type byUniqueTypeName []Type
@@ -627,6 +631,19 @@ func sortName(t Type) string {
return ""
}
+func sortMethods(list []*Func) {
+ sort.Sort(byUniqueMethodName(list))
+}
+
+func assertSortedMethods(list []*Func) {
+ if !debug {
+ panic("internal error: assertSortedMethods called outside debug mode")
+ }
+ if !sort.IsSorted(byUniqueMethodName(list)) {
+ panic("internal error: methods not sorted")
+ }
+}
+
// byUniqueMethodName method lists can be sorted by their unique method names.
type byUniqueMethodName []*Func
From c48d1503ba5d0f74bbc5cae5036bf225c6823a44 Mon Sep 17 00:00:00 2001
From: Rob Findley
Date: Thu, 4 Feb 2021 12:24:10 -0500
Subject: [PATCH 06/47] [dev.regabi] go/types: report unused packages in source
order
This is a port of CL 287072 to go/types.
Change-Id: I08f56995f0323c1f238d1b44703a481d393471d5
Reviewed-on: https://go-review.googlesource.com/c/go/+/289720
Run-TryBot: Robert Findley
TryBot-Result: Go Bot
Trust: Robert Findley
Trust: Robert Griesemer
Reviewed-by: Robert Griesemer
---
src/go/types/check.go | 36 +++++-----
src/go/types/resolver.go | 67 +++++++++----------
.../testdata/importdecl0/importdecl0b.src | 2 +-
.../testdata/importdecl1/importdecl1b.src | 2 +-
src/go/types/typexpr.go | 8 +--
5 files changed, 54 insertions(+), 61 deletions(-)
diff --git a/src/go/types/check.go b/src/go/types/check.go
index 280792e838..03798587e7 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -69,6 +69,12 @@ type importKey struct {
path, dir string
}
+// A dotImportKey describes a dot-imported object in the given scope.
+type dotImportKey struct {
+ scope *Scope
+ obj Object
+}
+
// A Checker maintains the state of the type checker.
// It must be created with NewChecker.
type Checker struct {
@@ -86,8 +92,9 @@ type Checker struct {
// information collected during type-checking of a set of package files
// (initialized by Files, valid only for the duration of check.Files;
// maps and lists are allocated on demand)
- files []*ast.File // package files
- unusedDotImports map[*Scope]map[*Package]*ast.ImportSpec // unused dot-imported packages
+ files []*ast.File // package files
+ imports []*PkgName // list of imported packages
+ dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
firstErr error // first error encountered
methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods
@@ -104,22 +111,6 @@ type Checker struct {
indent int // indentation for tracing
}
-// addUnusedImport adds the position of a dot-imported package
-// pkg to the map of dot imports for the given file scope.
-func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, spec *ast.ImportSpec) {
- mm := check.unusedDotImports
- if mm == nil {
- mm = make(map[*Scope]map[*Package]*ast.ImportSpec)
- check.unusedDotImports = mm
- }
- m := mm[scope]
- if m == nil {
- m = make(map[*Package]*ast.ImportSpec)
- mm[scope] = m
- }
- m[pkg] = spec
-}
-
// addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists
func (check *Checker) addDeclDep(to Object) {
from := check.decl
@@ -202,7 +193,8 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
func (check *Checker) initFiles(files []*ast.File) {
// start with a clean slate (check.Files may be called multiple times)
check.files = nil
- check.unusedDotImports = nil
+ check.imports = nil
+ check.dotImportMap = nil
check.firstErr = nil
check.methods = nil
@@ -272,10 +264,16 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
if !check.conf.DisableUnusedImportCheck {
check.unusedImports()
}
+ // no longer needed - release memory
+ check.imports = nil
+ check.dotImportMap = nil
check.recordUntyped()
check.pkg.complete = true
+
+ // TODO(rFindley) There's more memory we should release at this point.
+
return
}
diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go
index b637f8b8ca..cb66871883 100644
--- a/src/go/types/resolver.go
+++ b/src/go/types/resolver.go
@@ -275,21 +275,26 @@ func (check *Checker) collectObjects() {
}
}
- obj := NewPkgName(d.spec.Pos(), pkg, name, imp)
+ pkgName := NewPkgName(d.spec.Pos(), pkg, name, imp)
if d.spec.Name != nil {
// in a dot-import, the dot represents the package
- check.recordDef(d.spec.Name, obj)
+ check.recordDef(d.spec.Name, pkgName)
} else {
- check.recordImplicit(d.spec, obj)
+ check.recordImplicit(d.spec, pkgName)
}
if path == "C" {
// match cmd/compile (not prescribed by spec)
- obj.used = true
+ pkgName.used = true
}
// add import to file scope
+ check.imports = append(check.imports, pkgName)
if name == "." {
+ // dot-import
+ if check.dotImportMap == nil {
+ check.dotImportMap = make(map[dotImportKey]*PkgName)
+ }
// merge imported scope with file scope
for _, obj := range imp.scope.elems {
// A package scope may contain non-exported objects,
@@ -303,16 +308,15 @@ func (check *Checker) collectObjects() {
if alt := fileScope.Insert(obj); alt != nil {
check.errorf(d.spec.Name, _DuplicateDecl, "%s redeclared in this block", obj.Name())
check.reportAltDecl(alt)
+ } else {
+ check.dotImportMap[dotImportKey{fileScope, obj}] = pkgName
}
}
}
- // add position to set of dot-import positions for this file
- // (this is only needed for "imported but not used" errors)
- check.addUnusedDotImport(fileScope, imp, d.spec)
} else {
// declare imported package object in file scope
// (no need to provide s.Name since we called check.recordDef earlier)
- check.declare(fileScope, nil, obj, token.NoPos)
+ check.declare(fileScope, nil, pkgName, token.NoPos)
}
case constDecl:
// declare all constants
@@ -566,39 +570,30 @@ func (check *Checker) unusedImports() {
// any of its exported identifiers. To import a package solely for its side-effects
// (initialization), use the blank identifier as explicit package name."
- // check use of regular imported packages
- for _, scope := range check.pkg.scope.children /* file scopes */ {
- for _, obj := range scope.elems {
- if obj, ok := obj.(*PkgName); ok {
- // Unused "blank imports" are automatically ignored
- // since _ identifiers are not entered into scopes.
- if !obj.used {
- path := obj.imported.path
- base := pkgName(path)
- if obj.name == base {
- check.softErrorf(obj, _UnusedImport, "%q imported but not used", path)
- } else {
- check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name)
- }
- }
- }
- }
- }
-
- // check use of dot-imported packages
- for _, unusedDotImports := range check.unusedDotImports {
- for pkg, pos := range unusedDotImports {
- check.softErrorf(pos, _UnusedImport, "%q imported but not used", pkg.path)
+ for _, obj := range check.imports {
+ if !obj.used && obj.name != "_" {
+ check.errorUnusedPkg(obj)
}
}
}
-// pkgName returns the package name (last element) of an import path.
-func pkgName(path string) string {
- if i := strings.LastIndex(path, "/"); i >= 0 {
- path = path[i+1:]
+func (check *Checker) errorUnusedPkg(obj *PkgName) {
+ // If the package was imported with a name other than the final
+ // import path element, show it explicitly in the error message.
+ // Note that this handles both renamed imports and imports of
+ // packages containing unconventional package declarations.
+ // Note that this uses / always, even on Windows, because Go import
+ // paths always use forward slashes.
+ path := obj.imported.path
+ elem := path
+ if i := strings.LastIndex(elem, "/"); i >= 0 {
+ elem = elem[i+1:]
+ }
+ if obj.name == "" || obj.name == "." || obj.name == elem {
+ check.softErrorf(obj, _UnusedImport, "%q imported but not used", path)
+ } else {
+ check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name)
}
- return path
}
// dir makes a good-faith attempt to return the directory
diff --git a/src/go/types/testdata/importdecl0/importdecl0b.src b/src/go/types/testdata/importdecl0/importdecl0b.src
index 6844e70982..55690423b6 100644
--- a/src/go/types/testdata/importdecl0/importdecl0b.src
+++ b/src/go/types/testdata/importdecl0/importdecl0b.src
@@ -8,7 +8,7 @@ import "math"
import m "math"
import . "testing" // declares T in file scope
-import . /* ERROR "imported but not used" */ "unsafe"
+import . /* ERROR .unsafe. imported but not used */ "unsafe"
import . "fmt" // declares Println in file scope
import (
diff --git a/src/go/types/testdata/importdecl1/importdecl1b.src b/src/go/types/testdata/importdecl1/importdecl1b.src
index ee70bbd8e7..43a7bcd753 100644
--- a/src/go/types/testdata/importdecl1/importdecl1b.src
+++ b/src/go/types/testdata/importdecl1/importdecl1b.src
@@ -4,7 +4,7 @@
package importdecl1
-import . /* ERROR "imported but not used" */ "unsafe"
+import . /* ERROR .unsafe. imported but not used */ "unsafe"
type B interface {
A
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 311a970051..6e89ccb027 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -51,12 +51,12 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
}
assert(typ != nil)
- // The object may be dot-imported: If so, remove its package from
- // the map of unused dot imports for the respective file scope.
+ // The object may have been dot-imported.
+ // If so, mark the respective package as used.
// (This code is only needed for dot-imports. Without them,
// we only have to mark variables, see *Var case below).
- if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil {
- delete(check.unusedDotImports[scope], pkg)
+ if pkgName := check.dotImportMap[dotImportKey{scope, obj}]; pkgName != nil {
+ pkgName.used = true
}
switch obj := obj.(type) {
From e0ac989cf3e43ec77c7205a66cb1cd63dd4d3043 Mon Sep 17 00:00:00 2001
From: Emmanuel T Odeke
Date: Thu, 4 Feb 2021 01:39:18 -0800
Subject: [PATCH 07/47] archive/tar: detect out of bounds accesses in PAX
records resulting from padded lengths
Handles the case in which padding of a PAX record's length field
violates invariants about the formatting of record, whereby it no
longer matches the prescribed format:
"%d %s=%s\n", , ,
as per:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_03
0-padding, and paddings of other sorts weren't handled and we assumed
that only non-padded decimal lengths would be passed in.
Added test cases to ensure that the parsing still proceeds as expected.
The prior crashing repro:
0000000000000000000000000000000030 mtime=1432668921.098285006\n30 ctime=2147483649.15163319
exposed the fallacy in the code, that assumed that the length would ALWAYS be a
non-padded decimal length string.
This bug has existed since Go1.1 as per CL 6700047.
Thanks to Josh Bleecher Snyder for fuzzing this package, and thanks to Tom
Thorogood for advocacy, raising parity with GNU Tar, but for providing more test cases.
Fixes #40196
Change-Id: I32e0af4887bc9221481bd9e8a5120a79f177f08c
Reviewed-on: https://go-review.googlesource.com/c/go/+/289629
Trust: Emmanuel Odeke
Trust: Joe Tsai
Run-TryBot: Emmanuel Odeke
TryBot-Result: Go Bot
Reviewed-by: Joe Tsai
---
src/archive/tar/strconv.go | 21 ++++++++++++++++++++-
src/archive/tar/strconv_test.go | 7 +++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/src/archive/tar/strconv.go b/src/archive/tar/strconv.go
index 6d0a403808..f0b61e6dba 100644
--- a/src/archive/tar/strconv.go
+++ b/src/archive/tar/strconv.go
@@ -265,8 +265,27 @@ func parsePAXRecord(s string) (k, v, r string, err error) {
return "", "", s, ErrHeader
}
+ afterSpace := int64(sp + 1)
+ beforeLastNewLine := n - 1
+ // In some cases, "length" was perhaps padded/malformed, and
+ // trying to index past where the space supposedly is goes past
+ // the end of the actual record.
+ // For example:
+ // "0000000000000000000000000000000030 mtime=1432668921.098285006\n30 ctime=2147483649.15163319"
+ // ^ ^
+ // | |
+ // | afterSpace=35
+ // |
+ // beforeLastNewLine=29
+ // yet indexOf(firstSpace) MUST BE before endOfRecord.
+ //
+ // See https://golang.org/issues/40196.
+ if afterSpace >= beforeLastNewLine {
+ return "", "", s, ErrHeader
+ }
+
// Extract everything between the space and the final newline.
- rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:]
+ rec, nl, rem := s[afterSpace:beforeLastNewLine], s[beforeLastNewLine:n], s[n:]
if nl != "\n" {
return "", "", s, ErrHeader
}
diff --git a/src/archive/tar/strconv_test.go b/src/archive/tar/strconv_test.go
index dd3505a758..add65e272a 100644
--- a/src/archive/tar/strconv_test.go
+++ b/src/archive/tar/strconv_test.go
@@ -368,6 +368,13 @@ func TestParsePAXRecord(t *testing.T) {
{"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
{"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
{"50 tooshort=\n", "50 tooshort=\n", "", "", false},
+ {"0000000000000000000000000000000030 mtime=1432668921.098285006\n30 ctime=2147483649.15163319", "0000000000000000000000000000000030 mtime=1432668921.098285006\n30 ctime=2147483649.15163319", "mtime", "1432668921.098285006", false},
+ {"06 k=v\n", "06 k=v\n", "", "", false},
+ {"00006 k=v\n", "00006 k=v\n", "", "", false},
+ {"000006 k=v\n", "000006 k=v\n", "", "", false},
+ {"000000 k=v\n", "000000 k=v\n", "", "", false},
+ {"0 k=v\n", "0 k=v\n", "", "", false},
+ {"+0000005 x=\n", "+0000005 x=\n", "", "", false},
}
for _, v := range vectors {
From 493363ccff354ab5ed133f6d5fac942ba6cc034a Mon Sep 17 00:00:00 2001
From: Rob Findley
Date: Mon, 8 Feb 2021 18:24:13 -0500
Subject: [PATCH 08/47] [dev.regabi] go/types: must not import a package called
"init"
This is a port of CL 287494 to go/types. The additional checks in
test/fixedbugs are included, though they won't be executed by go/types.
Support for errorcheckdir checks will be added to go/types in a later
CL.
Change-Id: I37e202ea5daf7d7b8fc6ae93a4c4dbd11762480f
Reviewed-on: https://go-review.googlesource.com/c/go/+/290570
Reviewed-by: Robert Griesemer
Trust: Robert Findley
Run-TryBot: Robert Findley
TryBot-Result: Go Bot
---
src/go/types/resolver.go | 25 ++++++++++---------
.../testdata/importdecl0/importdecl0a.src | 2 +-
test/fixedbugs/issue43962.dir/a.go | 5 ++++
test/fixedbugs/issue43962.dir/b.go | 7 ++++++
test/fixedbugs/issue43962.go | 9 +++++++
5 files changed, 35 insertions(+), 13 deletions(-)
create mode 100644 test/fixedbugs/issue43962.dir/a.go
create mode 100644 test/fixedbugs/issue43962.dir/b.go
create mode 100644 test/fixedbugs/issue43962.go
diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go
index cb66871883..47e165db36 100644
--- a/src/go/types/resolver.go
+++ b/src/go/types/resolver.go
@@ -252,14 +252,6 @@ func (check *Checker) collectObjects() {
return
}
- // add package to list of explicit imports
- // (this functionality is provided as a convenience
- // for clients; it is not needed for type-checking)
- if !pkgImports[imp] {
- pkgImports[imp] = true
- pkg.imports = append(pkg.imports, imp)
- }
-
// local name overrides imported package name
name := imp.name
if d.spec.Name != nil {
@@ -269,10 +261,19 @@ func (check *Checker) collectObjects() {
check.errorf(d.spec.Name, _ImportCRenamed, `cannot rename import "C"`)
return
}
- if name == "init" {
- check.errorf(d.spec.Name, _InvalidInitDecl, "cannot declare init - must be func")
- return
- }
+ }
+
+ if name == "init" {
+ check.errorf(d.spec.Name, _InvalidInitDecl, "cannot import package as init - init must be a func")
+ return
+ }
+
+ // add package to list of explicit imports
+ // (this functionality is provided as a convenience
+ // for clients; it is not needed for type-checking)
+ if !pkgImports[imp] {
+ pkgImports[imp] = true
+ pkg.imports = append(pkg.imports, imp)
}
pkgName := NewPkgName(d.spec.Pos(), pkg, name, imp)
diff --git a/src/go/types/testdata/importdecl0/importdecl0a.src b/src/go/types/testdata/importdecl0/importdecl0a.src
index e96fca3cdd..5ceb96e1fa 100644
--- a/src/go/types/testdata/importdecl0/importdecl0a.src
+++ b/src/go/types/testdata/importdecl0/importdecl0a.src
@@ -10,7 +10,7 @@ import (
// we can have multiple blank imports (was bug)
_ "math"
_ "net/rpc"
- init /* ERROR "cannot declare init" */ "fmt"
+ init /* ERROR "cannot import package as init" */ "fmt"
// reflect defines a type "flag" which shows up in the gc export data
"reflect"
. /* ERROR "imported but not used" */ "reflect"
diff --git a/test/fixedbugs/issue43962.dir/a.go b/test/fixedbugs/issue43962.dir/a.go
new file mode 100644
index 0000000000..168b2063b4
--- /dev/null
+++ b/test/fixedbugs/issue43962.dir/a.go
@@ -0,0 +1,5 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package init
diff --git a/test/fixedbugs/issue43962.dir/b.go b/test/fixedbugs/issue43962.dir/b.go
new file mode 100644
index 0000000000..f55fea11c1
--- /dev/null
+++ b/test/fixedbugs/issue43962.dir/b.go
@@ -0,0 +1,7 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a" // ERROR "cannot import package as init"
diff --git a/test/fixedbugs/issue43962.go b/test/fixedbugs/issue43962.go
new file mode 100644
index 0000000000..dca4d077d5
--- /dev/null
+++ b/test/fixedbugs/issue43962.go
@@ -0,0 +1,9 @@
+// errorcheckdir
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 43962: Importing a package called "init" is an error.
+
+package ignored
From 1c58fcf7ed917f66e2b7f77f251e7e63ca9630e2 Mon Sep 17 00:00:00 2001
From: Rob Findley
Date: Mon, 8 Feb 2021 18:04:58 -0500
Subject: [PATCH 09/47] [dev.regabi] go/types: handle untyped constant
arithmetic overflow
This is a port of CL 287832 for go/types. It differs from that CL in its
handling of position data. Unlike the syntax package, which has a
unified Operation node, go/types checks operations for ast.UnaryExpr,
IncDecStmt, and BinaryExpr. It was simpler to keep the existing position
logic. Notably, this correctly puts the errors on the operator.
Change-Id: Id1e3aefe863da225eb0a9b3628cfc8a5684c0c4f
Reviewed-on: https://go-review.googlesource.com/c/go/+/290569
Run-TryBot: Robert Findley
TryBot-Result: Go Bot
Reviewed-by: Robert Griesemer
Trust: Robert Findley
---
src/go/types/expr.go | 133 +++++++++++++++++++------------
src/go/types/stdlib_test.go | 1 -
src/go/types/testdata/const0.src | 7 ++
3 files changed, 88 insertions(+), 53 deletions(-)
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index f7fb0caedd..2741cc635d 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -78,13 +78,60 @@ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
return true
}
+// overflow checks that the constant x is representable by its type.
+// For untyped constants, it checks that the value doesn't become
+// arbitrarily large.
+func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) {
+ assert(x.mode == constant_)
+
+ what := "" // operator description, if any
+ if int(op) < len(op2str) {
+ what = op2str[op]
+ }
+
+ if x.val.Kind() == constant.Unknown {
+ // TODO(gri) We should report exactly what went wrong. At the
+ // moment we don't have the (go/constant) API for that.
+ // See also TODO in go/constant/value.go.
+ check.errorf(atPos(opPos), _InvalidConstVal, "constant result is not representable")
+ return
+ }
+
+ // Typed constants must be representable in
+ // their type after each constant operation.
+ if typ, ok := x.typ.Underlying().(*Basic); ok && isTyped(typ) {
+ check.representable(x, typ)
+ return
+ }
+
+ // Untyped integer values must not grow arbitrarily.
+ const limit = 4 * 512 // 512 is the constant precision - we need more because old tests had no limits
+ if x.val.Kind() == constant.Int && constant.BitLen(x.val) > limit {
+ check.errorf(atPos(opPos), _InvalidConstVal, "constant %s overflow", what)
+ x.val = constant.MakeUnknown()
+ }
+}
+
+// This is only used for operations that may cause overflow.
+var op2str = [...]string{
+ token.ADD: "addition",
+ token.SUB: "subtraction",
+ token.XOR: "bitwise XOR",
+ token.MUL: "multiplication",
+ token.SHL: "shift",
+}
+
// The unary expression e may be nil. It's passed in for better error messages only.
-func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
- switch op {
+func (check *Checker) unary(x *operand, e *ast.UnaryExpr) {
+ check.expr(x, e.X)
+ if x.mode == invalid {
+ return
+ }
+ switch e.Op {
case token.AND:
// spec: "As an exception to the addressability
// requirement x may also be a composite literal."
- if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable {
+ if _, ok := unparen(e.X).(*ast.CompositeLit); !ok && x.mode != variable {
check.invalidOp(x, _UnaddressableOperand, "cannot take address of %s", x)
x.mode = invalid
return
@@ -111,26 +158,23 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
return
}
- if !check.op(unaryOpPredicates, x, op) {
+ if !check.op(unaryOpPredicates, x, e.Op) {
x.mode = invalid
return
}
if x.mode == constant_ {
- typ := x.typ.Underlying().(*Basic)
+ if x.val.Kind() == constant.Unknown {
+ // nothing to do (and don't cause an error below in the overflow check)
+ return
+ }
var prec uint
- if isUnsigned(typ) {
- prec = uint(check.conf.sizeof(typ) * 8)
- }
- x.val = constant.UnaryOp(op, x.val, prec)
- // Typed constants must be representable in
- // their type after each constant operation.
- if isTyped(typ) {
- if e != nil {
- x.expr = e // for better error message
- }
- check.representable(x, typ)
+ if isUnsigned(x.typ) {
+ prec = uint(check.conf.sizeof(x.typ) * 8)
}
+ x.val = constant.UnaryOp(e.Op, x.val, prec)
+ x.expr = e
+ check.overflow(x, e.Op, x.Pos())
return
}
@@ -667,7 +711,8 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
x.typ = Typ[UntypedBool]
}
-func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
+// If e != nil, it must be the shift expression; it may be nil for non-constant shifts.
+func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) {
untypedx := isUntyped(x.typ)
var xval constant.Value
@@ -735,14 +780,12 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
}
// x is a constant so xval != nil and it must be of Int kind.
x.val = constant.Shift(xval, op, uint(s))
- // Typed constants must be representable in
- // their type after each constant operation.
- if isTyped(x.typ) {
- if e != nil {
- x.expr = e // for better error message
- }
- check.representable(x, x.typ.Underlying().(*Basic))
+ x.expr = e
+ opPos := x.Pos()
+ if b, _ := e.(*ast.BinaryExpr); b != nil {
+ opPos = b.OpPos
}
+ check.overflow(x, op, opPos)
return
}
@@ -803,8 +846,9 @@ var binaryOpPredicates = opPredicates{
token.LOR: isBoolean,
}
-// The binary expression e may be nil. It's passed in for better error messages only.
-func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, op token.Token, opPos token.Pos) {
+// If e != nil, it must be the binary expression; it may be nil for non-constant expressions
+// (when invoked for an assignment operation where the binary expression is implicit).
+func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token.Token, opPos token.Pos) {
var y operand
check.expr(x, lhs)
@@ -879,30 +923,19 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
}
if x.mode == constant_ && y.mode == constant_ {
- xval := x.val
- yval := y.val
- typ := x.typ.Underlying().(*Basic)
+ // if either x or y has an unknown value, the result is unknown
+ if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown {
+ x.val = constant.MakeUnknown()
+ // x.typ is unchanged
+ return
+ }
// force integer division of integer operands
- if op == token.QUO && isInteger(typ) {
+ if op == token.QUO && isInteger(x.typ) {
op = token.QUO_ASSIGN
}
- x.val = constant.BinaryOp(xval, op, yval)
- // report error if valid operands lead to an invalid result
- if xval.Kind() != constant.Unknown && yval.Kind() != constant.Unknown && x.val.Kind() == constant.Unknown {
- // TODO(gri) We should report exactly what went wrong. At the
- // moment we don't have the (go/constant) API for that.
- // See also TODO in go/constant/value.go.
- check.errorf(atPos(opPos), _InvalidConstVal, "constant result is not representable")
- // TODO(gri) Should we mark operands with unknown values as invalid?
- }
- // Typed constants must be representable in
- // their type after each constant operation.
- if isTyped(typ) {
- if e != nil {
- x.expr = e // for better error message
- }
- check.representable(x, typ)
- }
+ x.val = constant.BinaryOp(x.val, op, y.val)
+ x.expr = e
+ check.overflow(x, op, opPos)
return
}
@@ -1538,11 +1571,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
}
case *ast.UnaryExpr:
- check.expr(x, e.X)
- if x.mode == invalid {
- goto Error
- }
- check.unary(x, e, e.Op)
+ check.unary(x, e)
if x.mode == invalid {
goto Error
}
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index 63e31f3d74..8a1e2905a7 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -171,7 +171,6 @@ func TestStdFixed(t *testing.T) {
testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
"issue6889.go", // gc-specific test
- "issue7746.go", // large constants - consumes too much memory
"issue11362.go", // canonical import path check
"issue16369.go", // go/types handles this correctly - not an issue
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
diff --git a/src/go/types/testdata/const0.src b/src/go/types/testdata/const0.src
index adbbf2863b..2916af5490 100644
--- a/src/go/types/testdata/const0.src
+++ b/src/go/types/testdata/const0.src
@@ -348,3 +348,10 @@ const _ = unsafe.Sizeof(func() {
assert(one == 1)
assert(iota == 0)
})
+
+// untyped constants must not get arbitrarily large
+const (
+ huge = 1<<1000
+ _ = huge * huge * /* ERROR constant multiplication overflow */ huge
+ _ = huge << 1000 << /* ERROR constant shift overflow */ 1000
+)
From 0a62067708938020e10b8142b4017edeac1b1f52 Mon Sep 17 00:00:00 2001
From: Rob Findley
Date: Mon, 8 Feb 2021 21:53:29 -0500
Subject: [PATCH 10/47] [dev.regabi] go/types: adjust importer to match
compiler importer
This is an exact port of CL 288632 to go/types.
Change-Id: Ie46e13355bdd0713b392e042844bab8491a16504
Reviewed-on: https://go-review.googlesource.com/c/go/+/290629
Trust: Robert Findley
Run-TryBot: Robert Findley
TryBot-Result: Go Bot
Reviewed-by: Robert Griesemer
---
src/go/internal/gcimporter/iimport.go | 52 +++++++++++----------------
1 file changed, 20 insertions(+), 32 deletions(-)
diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go
index c59dd16533..a3184e7641 100644
--- a/src/go/internal/gcimporter/iimport.go
+++ b/src/go/internal/gcimporter/iimport.go
@@ -15,6 +15,7 @@ import (
"go/token"
"go/types"
"io"
+ "math/big"
"sort"
)
@@ -320,7 +321,9 @@ func (r *importReader) value() (typ types.Type, val constant.Value) {
val = constant.MakeString(r.string())
case types.IsInteger:
- val = r.mpint(b)
+ var x big.Int
+ r.mpint(&x, b)
+ val = constant.Make(&x)
case types.IsFloat:
val = r.mpfloat(b)
@@ -365,8 +368,8 @@ func intSize(b *types.Basic) (signed bool, maxBytes uint) {
return
}
-func (r *importReader) mpint(b *types.Basic) constant.Value {
- signed, maxBytes := intSize(b)
+func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
+ signed, maxBytes := intSize(typ)
maxSmall := 256 - maxBytes
if signed {
@@ -385,7 +388,8 @@ func (r *importReader) mpint(b *types.Basic) constant.Value {
v = ^v
}
}
- return constant.MakeInt64(v)
+ x.SetInt64(v)
+ return
}
v := -n
@@ -395,39 +399,23 @@ func (r *importReader) mpint(b *types.Basic) constant.Value {
if v < 1 || uint(v) > maxBytes {
errorf("weird decoding: %v, %v => %v", n, signed, v)
}
-
- buf := make([]byte, v)
- io.ReadFull(&r.declReader, buf)
-
- // convert to little endian
- // TODO(gri) go/constant should have a more direct conversion function
- // (e.g., once it supports a big.Float based implementation)
- for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
- buf[i], buf[j] = buf[j], buf[i]
- }
-
- x := constant.MakeFromBytes(buf)
+ b := make([]byte, v)
+ io.ReadFull(&r.declReader, b)
+ x.SetBytes(b)
if signed && n&1 != 0 {
- x = constant.UnaryOp(token.SUB, x, 0)
+ x.Neg(x)
}
- return x
}
-func (r *importReader) mpfloat(b *types.Basic) constant.Value {
- x := r.mpint(b)
- if constant.Sign(x) == 0 {
- return x
+func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
+ var mant big.Int
+ r.mpint(&mant, typ)
+ var f big.Float
+ f.SetInt(&mant)
+ if f.Sign() != 0 {
+ f.SetMantExp(&f, int(r.int64()))
}
-
- exp := r.int64()
- switch {
- case exp > 0:
- x = constant.Shift(x, token.SHL, uint(exp))
- case exp < 0:
- d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
- x = constant.BinaryOp(x, token.QUO, d)
- }
- return x
+ return constant.Make(&f)
}
func (r *importReader) ident() string {
From 168d6a49a5ecbdd6a1eb039b2398c2821b3d3865 Mon Sep 17 00:00:00 2001
From: Rob Findley
Date: Mon, 8 Feb 2021 22:37:48 -0500
Subject: [PATCH 11/47] [dev.regabi] go/types: use 512 bits as max. integer
precision
This is a port of CL 288633 to go/types. It differs from that CL
in the implementation of opName, which now uses ast Exprs.
Additionally, a couple tests had to be updated:
+ TestEvalArith is updated to not overflow.
+ stmt0.src is updated to have an error positioned on the '<<'
operator.
Change-Id: I628357c33a1e7b0bb5bb7de5736f1fb10ce404e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/290630
Trust: Robert Findley
Run-TryBot: Robert Findley
TryBot-Result: Go Bot
Reviewed-by: Robert Griesemer
---
src/go/types/eval_test.go | 2 +-
src/go/types/expr.go | 46 +++++++++++++++++++++++-------
src/go/types/stdlib_test.go | 1 -
src/go/types/testdata/builtins.src | 10 +++----
src/go/types/testdata/const0.src | 16 +++++++----
src/go/types/testdata/const1.src | 18 ++++++++++--
src/go/types/testdata/stmt0.src | 2 +-
7 files changed, 69 insertions(+), 26 deletions(-)
diff --git a/src/go/types/eval_test.go b/src/go/types/eval_test.go
index d940bf0e80..3a97ac0471 100644
--- a/src/go/types/eval_test.go
+++ b/src/go/types/eval_test.go
@@ -76,7 +76,7 @@ func TestEvalArith(t *testing.T) {
`false == false`,
`12345678 + 87654321 == 99999999`,
`10 * 20 == 200`,
- `(1<<1000)*2 >> 100 == 2<<900`,
+ `(1<<500)*2 >> 100 == 2<<400`,
`"foo" + "bar" == "foobar"`,
`"abc" <= "bcd"`,
`len([10]struct{}{}) == 2*5`,
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 2741cc635d..5e1fe28a43 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -84,11 +84,6 @@ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) {
assert(x.mode == constant_)
- what := "" // operator description, if any
- if int(op) < len(op2str) {
- what = op2str[op]
- }
-
if x.val.Kind() == constant.Unknown {
// TODO(gri) We should report exactly what went wrong. At the
// moment we don't have the (go/constant) API for that.
@@ -105,15 +100,37 @@ func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) {
}
// Untyped integer values must not grow arbitrarily.
- const limit = 4 * 512 // 512 is the constant precision - we need more because old tests had no limits
- if x.val.Kind() == constant.Int && constant.BitLen(x.val) > limit {
- check.errorf(atPos(opPos), _InvalidConstVal, "constant %s overflow", what)
+ const prec = 512 // 512 is the constant precision
+ if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
+ check.errorf(atPos(opPos), _InvalidConstVal, "constant %s overflow", opName(x.expr))
x.val = constant.MakeUnknown()
}
}
+// opName returns the name of an operation, or the empty string.
+// For now, only operations that might overflow are handled.
+// TODO(gri) Expand this to a general mechanism giving names to
+// nodes?
+func opName(e ast.Expr) string {
+ switch e := e.(type) {
+ case *ast.BinaryExpr:
+ if int(e.Op) < len(op2str2) {
+ return op2str2[e.Op]
+ }
+ case *ast.UnaryExpr:
+ if int(e.Op) < len(op2str1) {
+ return op2str1[e.Op]
+ }
+ }
+ return ""
+}
+
+var op2str1 = [...]string{
+ token.XOR: "bitwise complement",
+}
+
// This is only used for operations that may cause overflow.
-var op2str = [...]string{
+var op2str2 = [...]string{
token.ADD: "addition",
token.SUB: "subtraction",
token.XOR: "bitwise XOR",
@@ -763,8 +780,17 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) {
if x.mode == constant_ {
if y.mode == constant_ {
+ // if either x or y has an unknown value, the result is unknown
+ if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown {
+ x.val = constant.MakeUnknown()
+ // ensure the correct type - see comment below
+ if !isInteger(x.typ) {
+ x.typ = Typ[UntypedInt]
+ }
+ return
+ }
// rhs must be within reasonable bounds in constant shifts
- const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64
+ const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 (see issue #44057)
s, ok := constant.Uint64Val(yval)
if !ok || s > shiftBound {
check.invalidOp(y, _InvalidShiftCount, "invalid shift count %s", y)
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index 8a1e2905a7..71e14b85e5 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -175,7 +175,6 @@ func TestStdFixed(t *testing.T) {
"issue16369.go", // go/types handles this correctly - not an issue
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
"issue18882.go", // go/types doesn't check validity of //go:xxx directives
- "issue20232.go", // go/types handles larger constants than gc
"issue20529.go", // go/types does not have constraints on stack size
"issue22200.go", // go/types does not have constraints on stack size
"issue22200b.go", // go/types does not have constraints on stack size
diff --git a/src/go/types/testdata/builtins.src b/src/go/types/testdata/builtins.src
index a7613adc35..6ee28f13b4 100644
--- a/src/go/types/testdata/builtins.src
+++ b/src/go/types/testdata/builtins.src
@@ -514,7 +514,7 @@ func panic1() {
panic("foo")
panic(false)
panic(1<<10)
- panic(1 /* ERROR overflows */ <<1000)
+ panic(1 << /* ERROR constant shift overflow */ 1000)
_ = panic /* ERROR used as value */ (0)
var s []byte
@@ -538,7 +538,7 @@ func print1() {
print(2.718281828)
print(false)
print(1<<10)
- print(1 /* ERROR overflows */ <<1000)
+ print(1 << /* ERROR constant shift overflow */ 1000)
println(nil /* ERROR untyped nil */ )
var s []int
@@ -564,7 +564,7 @@ func println1() {
println(2.718281828)
println(false)
println(1<<10)
- println(1 /* ERROR overflows */ <<1000)
+ println(1 << /* ERROR constant shift overflow */ 1000)
println(nil /* ERROR untyped nil */ )
var s []int
@@ -695,7 +695,7 @@ func Alignof1() {
_ = unsafe.Alignof(42)
_ = unsafe.Alignof(new(struct{}))
_ = unsafe.Alignof(1<<10)
- _ = unsafe.Alignof(1 /* ERROR overflows */ <<1000)
+ _ = unsafe.Alignof(1 << /* ERROR constant shift overflow */ 1000)
_ = unsafe.Alignof(nil /* ERROR "untyped nil */ )
unsafe /* ERROR not used */ .Alignof(x)
@@ -783,7 +783,7 @@ func Sizeof1() {
_ = unsafe.Sizeof(42)
_ = unsafe.Sizeof(new(complex128))
_ = unsafe.Sizeof(1<<10)
- _ = unsafe.Sizeof(1 /* ERROR overflows */ <<1000)
+ _ = unsafe.Sizeof(1 << /* ERROR constant shift overflow */ 1000)
_ = unsafe.Sizeof(nil /* ERROR untyped nil */ )
unsafe /* ERROR not used */ .Sizeof(x)
diff --git a/src/go/types/testdata/const0.src b/src/go/types/testdata/const0.src
index 2916af5490..5608b1549b 100644
--- a/src/go/types/testdata/const0.src
+++ b/src/go/types/testdata/const0.src
@@ -350,8 +350,14 @@ const _ = unsafe.Sizeof(func() {
})
// untyped constants must not get arbitrarily large
-const (
- huge = 1<<1000
- _ = huge * huge * /* ERROR constant multiplication overflow */ huge
- _ = huge << 1000 << /* ERROR constant shift overflow */ 1000
-)
+const prec = 512 // internal maximum precision for integers
+const maxInt = (1<<(prec/2) - 1) * (1<<(prec/2) + 1) // == 1<
Date: Thu, 4 Feb 2021 15:26:52 -0500
Subject: [PATCH 12/47] cmd/go: suppress errors from 'go get -d' for packages
that only conditionally exist
Fixes #44106
Fixes #29268
Change-Id: Id113f2ced274d43fbf66cb804581448218996f81
Reviewed-on: https://go-review.googlesource.com/c/go/+/289769
TryBot-Result: Go Bot
Reviewed-by: Jay Conrod
Trust: Bryan C. Mills
Run-TryBot: Bryan C. Mills
---
src/cmd/go/internal/modget/get.go | 20 ++-
.../go/testdata/script/mod_get_pkgtags.txt | 116 ++++++++++++++++++
2 files changed, 131 insertions(+), 5 deletions(-)
create mode 100644 src/cmd/go/testdata/script/mod_get_pkgtags.txt
diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go
index 574f3e194d..1a8c9d3725 100644
--- a/src/cmd/go/internal/modget/get.go
+++ b/src/cmd/go/internal/modget/get.go
@@ -380,10 +380,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
pkgs := load.PackagesAndErrors(ctx, pkgPatterns)
load.CheckPackageErrors(pkgs)
work.InstallPackages(ctx, pkgPatterns, pkgs)
- // TODO(#40276): After Go 1.16, print a deprecation notice when building
- // and installing main packages. 'go install pkg' or
- // 'go install pkg@version' should be used instead.
- // Give the specific argument to use if possible.
+ // TODO(#40276): After Go 1.16, print a deprecation notice when building and
+ // installing main packages. 'go install pkg' or 'go install pkg@version'
+ // should be used instead. Give the specific argument to use if possible.
}
if !modload.HasModRoot() {
@@ -1453,7 +1452,18 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
}
}
for _, pkg := range pkgs {
- if _, _, err := modload.Lookup("", false, pkg); err != nil {
+ if dir, _, err := modload.Lookup("", false, pkg); err != nil {
+ if dir != "" && errors.Is(err, imports.ErrNoGo) {
+ // Since dir is non-empty, we must have located source files
+ // associated with either the package or its test — ErrNoGo must
+ // indicate that none of those source files happen to apply in this
+ // configuration. If we are actually building the package (no -d
+ // flag), the compiler will report the problem; otherwise, assume that
+ // the user is going to build or test it in some other configuration
+ // and suppress the error.
+ continue
+ }
+
base.SetExitStatus(1)
if ambiguousErr := (*modload.AmbiguousImportError)(nil); errors.As(err, &ambiguousErr) {
for _, m := range ambiguousErr.Modules {
diff --git a/src/cmd/go/testdata/script/mod_get_pkgtags.txt b/src/cmd/go/testdata/script/mod_get_pkgtags.txt
new file mode 100644
index 0000000000..c0a57f3fab
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_pkgtags.txt
@@ -0,0 +1,116 @@
+# https://golang.org/issue/44106
+# 'go get' should fetch the transitive dependencies of packages regardless of
+# tags, but shouldn't error out if the package is missing tag-guarded
+# dependencies.
+
+# Control case: just adding the top-level module to the go.mod file does not
+# fetch its dependencies.
+
+go mod edit -require example.net/tools@v0.1.0
+! go list -deps example.net/cmd/tool
+stderr '^module example\.net/cmd provides package example\.net/cmd/tool and is replaced but not required; to add it:\n\tgo get example\.net/cmd@v0\.1\.0$'
+go mod edit -droprequire example.net/tools
+
+
+# 'go get -d' makes a best effort to fetch those dependencies, but shouldn't
+# error out if dependencies of tag-guarded files are missing.
+
+go get -d example.net/tools@v0.1.0
+
+! go list example.net/tools
+stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$'
+
+go list -tags=tools -e -deps example.net/tools
+stdout '^example.net/cmd/tool$'
+stdout '^example.net/missing$'
+
+go list -deps example.net/cmd/tool
+
+! go list example.net/missing
+stderr '^no required module provides package example.net/missing; to add it:\n\tgo get example.net/missing$'
+
+
+# https://golang.org/issue/29268
+# 'go get' should fetch modules whose roots contain test-only packages, but
+# without the -t flag shouldn't error out if the test has missing dependencies.
+
+go get -d example.net/testonly@v0.1.0
+
+# With the -t flag, the test dependencies must resolve successfully.
+! go get -d -t example.net/testonly@v0.1.0
+stderr '^example.net/testonly tested by\n\texample.net/testonly\.test imports\n\texample.net/missing: cannot find module providing package example.net/missing$'
+
+
+# 'go get -d' should succeed for a module path that does not contain a package,
+# but fail for a non-package subdirectory of a module.
+
+! go get -d example.net/missing/subdir@v0.1.0
+stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+go get -d example.net/missing@v0.1.0
+
+
+# Getting the subdirectory should continue to fail even if the corresponding
+# module is already present in the build list.
+
+! go get -d example.net/missing/subdir@v0.1.0
+stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+
+-- go.mod --
+module example.net/m
+
+go 1.15
+
+replace (
+ example.net/tools v0.1.0 => ./tools
+ example.net/cmd v0.1.0 => ./cmd
+ example.net/testonly v0.1.0 => ./testonly
+ example.net/missing v0.1.0 => ./missing
+)
+
+-- tools/go.mod --
+module example.net/tools
+
+go 1.15
+
+// Requirements intentionally omitted.
+
+-- tools/tools.go --
+// +build tools
+
+package tools
+
+import (
+ _ "example.net/cmd/tool"
+ _ "example.net/missing"
+)
+
+-- cmd/go.mod --
+module example.net/cmd
+
+go 1.16
+-- cmd/tool/tool.go --
+package main
+
+func main() {}
+
+-- testonly/go.mod --
+module example.net/testonly
+
+go 1.15
+-- testonly/testonly_test.go --
+package testonly_test
+
+import _ "example.net/missing"
+
+func Test(t *testing.T) {}
+
+-- missing/go.mod --
+module example.net/missing
+
+go 1.15
+-- missing/README.txt --
+There are no Go source files here.
+-- missing/subdir/README.txt --
+There are no Go source files here either.
From 59703d53e249db738363c3fab9143348ff9559ea Mon Sep 17 00:00:00 2001
From: Cherry Zhang
Date: Fri, 5 Feb 2021 18:07:46 -0500
Subject: [PATCH 13/47] [dev.regabi] cmd/link: stop using ABI aliases if
wrapper is enabled
If ABI wrappers are enabled, we should not see ABI aliases at
link time. Stop resolving them. One exception is shared linkage,
where we still use ABI aliases as we don't always know the ABI
for symbols from shared libraries.
Change-Id: Ia89a788094382adeb4c4ef9b0312aa6e8c2f79ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/290032
TryBot-Result: Go Bot
Reviewed-by: Than McIntosh
Trust: Cherry Zhang
Run-TryBot: Cherry Zhang
---
src/cmd/link/internal/ld/lib.go | 8 +++++++-
src/cmd/link/internal/loader/loader.go | 4 ++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 71cef0b774..314896824a 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -489,10 +489,16 @@ func (ctxt *Link) loadlib() {
case 0:
// nothing to do
case 1, 2:
- flags = loader.FlagStrictDups
+ flags |= loader.FlagStrictDups
default:
log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
}
+ if !*flagAbiWrap || ctxt.linkShared {
+ // Use ABI aliases if ABI wrappers are not used.
+ // TODO: for now we still use ABI aliases in shared linkage, even if
+ // the wrapper is enabled.
+ flags |= loader.FlagUseABIAlias
+ }
elfsetstring1 := func(str string, off int) { elfsetstring(ctxt, 0, str, off) }
ctxt.loader = loader.NewLoader(flags, elfsetstring1, &ctxt.ErrorReporter.ErrorReporter)
ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index 971cc432ff..98c2131c2b 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -322,6 +322,7 @@ type extSymPayload struct {
const (
// Loader.flags
FlagStrictDups = 1 << iota
+ FlagUseABIAlias
)
func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorReporter) *Loader {
@@ -2270,6 +2271,9 @@ func abiToVer(abi uint16, localSymVersion int) int {
// symbol. If the sym in question is not an alias, the sym itself is
// returned.
func (l *Loader) ResolveABIAlias(s Sym) Sym {
+ if l.flags&FlagUseABIAlias == 0 {
+ return s
+ }
if s == 0 {
return 0
}
From ed8079096fe2e78d6dcb8002758774dca6d24eee Mon Sep 17 00:00:00 2001
From: Cherry Zhang
Date: Wed, 10 Feb 2021 12:43:18 -0500
Subject: [PATCH 14/47] cmd/compile: mark concrete call of
reflect.(*rtype).Method as REFLECTMETHOD
For functions that call reflect.Type.Method (or MethodByName), we
mark it as REFLECTMETHOD, which tells the linker that methods
can be retrieved via reflection and the linker keeps all exported
methods live. Currently, this marking expects exactly the
interface call reflect.Type.Method (or MethodByName). But now the
compiler can devirtualize that call to a concrete call
reflect.(*rtype).Method (or MethodByName), which is not handled
and causing the linker to discard methods too aggressively.
Handle the latter in this CL.
Fixes #44207.
Change-Id: Ia4060472dbff6ab6a83d2ca8e60a3e3f180ee832
Reviewed-on: https://go-review.googlesource.com/c/go/+/290950
Trust: Cherry Zhang
Reviewed-by: Matthew Dempsky
---
src/cmd/compile/internal/gc/walk.go | 16 +++++++++++++++-
test/reflectmethod7.go | 24 ++++++++++++++++++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
create mode 100644 test/reflectmethod7.go
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 2133a160b2..98ebb23991 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -550,8 +550,12 @@ opswitch:
case OCLOSUREVAR, OCFUNC:
case OCALLINTER, OCALLFUNC, OCALLMETH:
- if n.Op == OCALLINTER {
+ if n.Op == OCALLINTER || n.Op == OCALLMETH {
+ // We expect both interface call reflect.Type.Method and concrete
+ // call reflect.(*rtype).Method.
usemethod(n)
+ }
+ if n.Op == OCALLINTER {
markUsedIfaceMethod(n)
}
@@ -3710,6 +3714,16 @@ func usemethod(n *Node) {
}
}
+ // Don't mark reflect.(*rtype).Method, etc. themselves in the reflect package.
+ // Those functions may be alive via the itab, which should not cause all methods
+ // alive. We only want to mark their callers.
+ if myimportpath == "reflect" {
+ switch Curfn.Func.Nname.Sym.Name { // TODO: is there a better way than hardcoding the names?
+ case "(*rtype).Method", "(*rtype).MethodByName", "(*interfaceType).Method", "(*interfaceType).MethodByName":
+ return
+ }
+ }
+
// Note: Don't rely on res0.Type.String() since its formatting depends on multiple factors
// (including global variables such as numImports - was issue #19028).
// Also need to check for reflect package itself (see Issue #38515).
diff --git a/test/reflectmethod7.go b/test/reflectmethod7.go
new file mode 100644
index 0000000000..42429978b4
--- /dev/null
+++ b/test/reflectmethod7.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// See issue 44207.
+
+package main
+
+import "reflect"
+
+type S int
+
+func (s S) M() {}
+
+func main() {
+ t := reflect.TypeOf(S(0))
+ fn, ok := reflect.PtrTo(t).MethodByName("M")
+ if !ok {
+ panic("FAIL")
+ }
+ fn.Func.Call([]reflect.Value{reflect.New(t)})
+}
From e5b08e6d5cecb646066c0cadddf6300e2a10ffb2 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 9 Feb 2021 13:46:53 -0500
Subject: [PATCH 15/47] io/fs: allow backslash in ValidPath, reject in
os.DirFS.Open
Rejecting backslash introduces problems with presenting
underlying OS file systems that contain names with backslash.
Rejecting backslash also does not Windows-proof the syntax,
because colon can also be a path separator. And we are not
going to reject colon from all names. So don't reject backslash
either.
There is a similar problem on Windows with names containing
slashes, but those are more difficult (though not impossible)
to create.
Also document and enforce that paths must be UTF-8.
Fixes #44166.
Change-Id: Iac7a9a268025c1fd31010dbaf3f51e1660c7ae2a
Reviewed-on: https://go-review.googlesource.com/c/go/+/290709
TryBot-Result: Go Bot
Reviewed-by: Bryan C. Mills
Trust: Russ Cox
Run-TryBot: Russ Cox
---
src/io/fs/fs.go | 25 +++++++++++++++----------
src/io/fs/fs_test.go | 7 ++++---
src/os/file.go | 13 ++++++++++++-
src/os/os_test.go | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/src/io/fs/fs.go b/src/io/fs/fs.go
index c330f123ad..3d2e2ee2ac 100644
--- a/src/io/fs/fs.go
+++ b/src/io/fs/fs.go
@@ -10,6 +10,7 @@ package fs
import (
"internal/oserror"
"time"
+ "unicode/utf8"
)
// An FS provides access to a hierarchical file system.
@@ -32,15 +33,22 @@ type FS interface {
// ValidPath reports whether the given path name
// is valid for use in a call to Open.
-// Path names passed to open are unrooted, slash-separated
-// sequences of path elements, like “x/y/z”.
-// Path names must not contain a “.” or “..” or empty element,
-// except for the special case that the root directory is named “.”.
-// Leading and trailing slashes (like “/x” or “x/”) are not allowed.
//
-// Paths are slash-separated on all systems, even Windows.
-// Backslashes must not appear in path names.
+// Path names passed to open are UTF-8-encoded,
+// unrooted, slash-separated sequences of path elements, like “x/y/z”.
+// Path names must not contain an element that is “.” or “..” or the empty string,
+// except for the special case that the root directory is named “.”.
+// Paths must not start or end with a slash: “/x” and “x/” are invalid.
+//
+// Note that paths are slash-separated on all systems, even Windows.
+// Paths containing other characters such as backslash and colon
+// are accepted as valid, but those characters must never be
+// interpreted by an FS implementation as path element separators.
func ValidPath(name string) bool {
+ if !utf8.ValidString(name) {
+ return false
+ }
+
if name == "." {
// special case
return true
@@ -50,9 +58,6 @@ func ValidPath(name string) bool {
for {
i := 0
for i < len(name) && name[i] != '/' {
- if name[i] == '\\' {
- return false
- }
i++
}
elem := name[:i]
diff --git a/src/io/fs/fs_test.go b/src/io/fs/fs_test.go
index 8d395fc0db..aae1a7606f 100644
--- a/src/io/fs/fs_test.go
+++ b/src/io/fs/fs_test.go
@@ -33,9 +33,10 @@ var isValidPathTests = []struct {
{"x/..", false},
{"x/../y", false},
{"x//y", false},
- {`x\`, false},
- {`x\y`, false},
- {`\x`, false},
+ {`x\`, true},
+ {`x\y`, true},
+ {`x:y`, true},
+ {`\x`, true},
}
func TestValidPath(t *testing.T) {
diff --git a/src/os/file.go b/src/os/file.go
index 416bc0efa6..52dd94339b 100644
--- a/src/os/file.go
+++ b/src/os/file.go
@@ -620,10 +620,21 @@ func DirFS(dir string) fs.FS {
return dirFS(dir)
}
+func containsAny(s, chars string) bool {
+ for i := 0; i < len(s); i++ {
+ for j := 0; j < len(chars); j++ {
+ if s[i] == chars[j] {
+ return true
+ }
+ }
+ }
+ return false
+}
+
type dirFS string
func (dir dirFS) Open(name string) (fs.File, error) {
- if !fs.ValidPath(name) {
+ if !fs.ValidPath(name) || runtime.GOOS == "windows" && containsAny(name, `\:`) {
return nil, &PathError{Op: "open", Path: name, Err: ErrInvalid}
}
f, err := Open(string(dir) + "/" + name)
diff --git a/src/os/os_test.go b/src/os/os_test.go
index ee54b4aba1..a32e5fc11e 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -2719,6 +2719,40 @@ func TestDirFS(t *testing.T) {
if err := fstest.TestFS(DirFS("./testdata/dirfs"), "a", "b", "dir/x"); err != nil {
t.Fatal(err)
}
+
+ // Test that Open does not accept backslash as separator.
+ d := DirFS(".")
+ _, err := d.Open(`testdata\dirfs`)
+ if err == nil {
+ t.Fatalf(`Open testdata\dirfs succeeded`)
+ }
+}
+
+func TestDirFSPathsValid(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skipf("skipping on Windows")
+ }
+
+ d := t.TempDir()
+ if err := os.WriteFile(filepath.Join(d, "control.txt"), []byte(string("Hello, world!")), 0644); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(filepath.Join(d, `e:xperi\ment.txt`), []byte(string("Hello, colon and backslash!")), 0644); err != nil {
+ t.Fatal(err)
+ }
+
+ fsys := os.DirFS(d)
+ err := fs.WalkDir(fsys, ".", func(path string, e fs.DirEntry, err error) error {
+ if fs.ValidPath(e.Name()) {
+ t.Logf("%q ok", e.Name())
+ } else {
+ t.Errorf("%q INVALID", e.Name())
+ }
+ return nil
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
}
func TestReadFileProc(t *testing.T) {
From 930c2c9a6810b54d84dc499120219a6cb4563fd7 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 9 Feb 2021 17:34:09 -0500
Subject: [PATCH 16/47] cmd/go: reject embedded files that can't be packed into
modules
If the file won't be packed into a module,
don't put those files into embeds.
Otherwise people will be surprised when things work
locally but not when imported by another module.
Observed on CL 290709
Change-Id: Ia0ef7d0e0f5e42473c2b774e57c843e68a365bc7
Reviewed-on: https://go-review.googlesource.com/c/go/+/290809
Trust: Russ Cox
Run-TryBot: Russ Cox
TryBot-Result: Go Bot
Reviewed-by: Bryan C. Mills
Reviewed-by: Jay Conrod
---
src/cmd/go/internal/load/pkg.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 3a274a3ad1..8b12faf4cd 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -36,6 +36,8 @@ import (
"cmd/go/internal/str"
"cmd/go/internal/trace"
"cmd/internal/sys"
+
+ "golang.org/x/mod/module"
)
var IgnoreImports bool // control whether we ignore imports in packages
@@ -2090,6 +2092,9 @@ func validEmbedPattern(pattern string) bool {
// can't or won't be included in modules and therefore shouldn't be treated
// as existing for embedding.
func isBadEmbedName(name string) bool {
+ if err := module.CheckFilePath(name); err != nil {
+ return true
+ }
switch name {
// Empty string should be impossible but make it bad.
case "":
From 26ceae85a89dc4ea910cc0bfa209c85213a93725 Mon Sep 17 00:00:00 2001
From: DQNEO
Date: Wed, 10 Feb 2021 14:46:54 +0900
Subject: [PATCH 17/47] spec: More precise wording in section on function
calls.
A caller is not always in a function.
For example, a call can appear in top level declarations.
e.g. var x = f()
Change-Id: I29c4c3b7663249434fb2b8a6d0003267c77268cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/290849
Reviewed-by: Rob Pike
Reviewed-by: Ian Lance Taylor
Reviewed-by: Robert Griesemer
Trust: Robert Griesemer
---
doc/go_spec.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/go_spec.html b/doc/go_spec.html
index c9e14a3fec..59c9ce3c43 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
@@ -3446,7 +3446,7 @@ In a function call, the function value and arguments are evaluated in
After they are evaluated, the parameters of the call are passed by value to the function
and the called function begins execution.
The return parameters of the function are passed by value
-back to the calling function when the function returns.
+back to the caller when the function returns.
From 864d4f1c6b364e13c0a4008bc203f336b0027f44 Mon Sep 17 00:00:00 2001
From: Jay Conrod
Date: Thu, 11 Feb 2021 10:27:55 -0500
Subject: [PATCH 18/47] cmd/go: multiple small 'go help' fixes
* Link to privacy policies for proxy.golang.org and sum.golang.org in
'go help modules'. It's important that both policies are linked from
the go command's documentation.
* Fix wording and typo in 'go help vcs' following comments in CL 290992,
which adds reference documentation for GOVCS.
* Fix whitespace on GOVCS in 'go help environment'.
For #41730
Change-Id: I86abceacd4962b748361244026f219157c9285e9
Reviewed-on: https://go-review.googlesource.com/c/go/+/291230
Trust: Jay Conrod
Run-TryBot: Jay Conrod
Reviewed-by: Bryan C. Mills
TryBot-Result: Go Bot
---
src/cmd/go/alldocs.go | 30 +++++++++++++++++++++--------
src/cmd/go/internal/help/helpdoc.go | 2 +-
src/cmd/go/internal/modget/get.go | 17 +++++++++-------
src/cmd/go/internal/modload/help.go | 13 +++++++++++--
4 files changed, 44 insertions(+), 18 deletions(-)
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 49d390297c..e7c63f0749 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1808,7 +1808,7 @@
// The directory where the go command will write
// temporary source files, packages, and binaries.
// GOVCS
-// Lists version control commands that may be used with matching servers.
+// Lists version control commands that may be used with matching servers.
// See 'go help vcs'.
//
// Environment variables for use with cgo:
@@ -2410,6 +2410,17 @@
//
// For a detailed reference on modules, see https://golang.org/ref/mod.
//
+// By default, the go command may download modules from https://proxy.golang.org.
+// It may authenticate modules using the checksum database at
+// https://sum.golang.org. Both services are operated by the Go team at Google.
+// The privacy policies for these services are available at
+// https://proxy.golang.org/privacy and https://sum.golang.org/privacy,
+// respectively.
+//
+// The go command's download behavior may be configured using GOPROXY, GOSUMDB,
+// GOPRIVATE, and other environment variables. See 'go help environment'
+// and https://golang.org/ref/mod#private-module-privacy for more information.
+//
//
// Module authentication using go.sum
//
@@ -2868,20 +2879,23 @@
// legal reasons). Therefore, clients can still access public code served from
// Bazaar, Fossil, or Subversion repositories by default, because those downloads
// use the Go module mirror, which takes on the security risk of running the
-// version control commands, using a custom sandbox.
+// version control commands using a custom sandbox.
//
// The GOVCS variable can be used to change the allowed version control systems
// for specific packages (identified by a module or import path).
-// The GOVCS variable applies both when using modules and when using GOPATH.
-// When using modules, the patterns match against the module path.
-// When using GOPATH, the patterns match against the import path
-// corresponding to the root of the version control repository.
+// The GOVCS variable applies when building package in both module-aware mode
+// and GOPATH mode. When using modules, the patterns match against the module path.
+// When using GOPATH, the patterns match against the import path corresponding to
+// the root of the version control repository.
//
// The general form of the GOVCS setting is a comma-separated list of
// pattern:vcslist rules. The pattern is a glob pattern that must match
// one or more leading elements of the module or import path. The vcslist
// is a pipe-separated list of allowed version control commands, or "all"
-// to allow use of any known command, or "off" to allow nothing.
+// to allow use of any known command, or "off" to disallow all commands.
+// Note that if a module matches a pattern with vcslist "off", it may still be
+// downloaded if the origin server uses the "mod" scheme, which instructs the
+// go command to download the module using the GOPROXY protocol.
// The earliest matching pattern in the list applies, even if later patterns
// might also match.
//
@@ -2889,7 +2903,7 @@
//
// GOVCS=github.com:git,evil.com:off,*:git|hg
//
-// With this setting, code with an module or import path beginning with
+// With this setting, code with a module or import path beginning with
// github.com/ can only use git; paths on evil.com cannot use any version
// control command, and all other paths (* matches everything) can use
// only git or hg.
diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go
index e07ad0e1db..57cee4ff96 100644
--- a/src/cmd/go/internal/help/helpdoc.go
+++ b/src/cmd/go/internal/help/helpdoc.go
@@ -542,7 +542,7 @@ General-purpose environment variables:
The directory where the go command will write
temporary source files, packages, and binaries.
GOVCS
- Lists version control commands that may be used with matching servers.
+ Lists version control commands that may be used with matching servers.
See 'go help vcs'.
Environment variables for use with cgo:
diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go
index 1a8c9d3725..dccacd3d1e 100644
--- a/src/cmd/go/internal/modget/get.go
+++ b/src/cmd/go/internal/modget/get.go
@@ -176,20 +176,23 @@ packages or when the mirror refuses to serve a public package (typically for
legal reasons). Therefore, clients can still access public code served from
Bazaar, Fossil, or Subversion repositories by default, because those downloads
use the Go module mirror, which takes on the security risk of running the
-version control commands, using a custom sandbox.
+version control commands using a custom sandbox.
The GOVCS variable can be used to change the allowed version control systems
for specific packages (identified by a module or import path).
-The GOVCS variable applies both when using modules and when using GOPATH.
-When using modules, the patterns match against the module path.
-When using GOPATH, the patterns match against the import path
-corresponding to the root of the version control repository.
+The GOVCS variable applies when building package in both module-aware mode
+and GOPATH mode. When using modules, the patterns match against the module path.
+When using GOPATH, the patterns match against the import path corresponding to
+the root of the version control repository.
The general form of the GOVCS setting is a comma-separated list of
pattern:vcslist rules. The pattern is a glob pattern that must match
one or more leading elements of the module or import path. The vcslist
is a pipe-separated list of allowed version control commands, or "all"
-to allow use of any known command, or "off" to allow nothing.
+to allow use of any known command, or "off" to disallow all commands.
+Note that if a module matches a pattern with vcslist "off", it may still be
+downloaded if the origin server uses the "mod" scheme, which instructs the
+go command to download the module using the GOPROXY protocol.
The earliest matching pattern in the list applies, even if later patterns
might also match.
@@ -197,7 +200,7 @@ For example, consider:
GOVCS=github.com:git,evil.com:off,*:git|hg
-With this setting, code with an module or import path beginning with
+With this setting, code with a module or import path beginning with
github.com/ can only use git; paths on evil.com cannot use any version
control command, and all other paths (* matches everything) can use
only git or hg.
diff --git a/src/cmd/go/internal/modload/help.go b/src/cmd/go/internal/modload/help.go
index 1cb58961be..fd39ddd94e 100644
--- a/src/cmd/go/internal/modload/help.go
+++ b/src/cmd/go/internal/modload/help.go
@@ -6,8 +6,6 @@ package modload
import "cmd/go/internal/base"
-// TODO(rsc): The "module code layout" section needs to be written.
-
var HelpModules = &base.Command{
UsageLine: "modules",
Short: "modules, module versions, and more",
@@ -22,6 +20,17 @@ For a series of tutorials on modules, see
https://golang.org/doc/tutorial/create-module.
For a detailed reference on modules, see https://golang.org/ref/mod.
+
+By default, the go command may download modules from https://proxy.golang.org.
+It may authenticate modules using the checksum database at
+https://sum.golang.org. Both services are operated by the Go team at Google.
+The privacy policies for these services are available at
+https://proxy.golang.org/privacy and https://sum.golang.org/privacy,
+respectively.
+
+The go command's download behavior may be configured using GOPROXY, GOSUMDB,
+GOPRIVATE, and other environment variables. See 'go help environment'
+and https://golang.org/ref/mod#private-module-privacy for more information.
`,
}
From 249da7ec020e194208c02c8eb6a04d017bf29fea Mon Sep 17 00:00:00 2001
From: Carlos Amedee
Date: Wed, 10 Feb 2021 20:29:50 -0500
Subject: [PATCH 19/47] CONTRIBUTORS: update for the Go 1.16 release
This update was created using the updatecontrib command:
go get golang.org/x/build/cmd/updatecontrib
cd gotip
updatecontrib
With manual changes based on publicly available information
to canonicalize letter case and formatting for a few names.
For #12042.
Change-Id: I030b77e8ebcc7fe02106f0f264acdfb0b56e20d9
Reviewed-on: https://go-review.googlesource.com/c/go/+/291189
Trust: Carlos Amedee
Run-TryBot: Carlos Amedee
TryBot-Result: Go Bot
Reviewed-by: Ian Lance Taylor
Reviewed-by: Alexander Rakoczy
Reviewed-by: Dmitri Shuralyov
---
CONTRIBUTORS | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 158 insertions(+)
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index cebc92f53f..ccbe4627f3 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -30,6 +30,7 @@ Aaron Bieber
Aaron Cannon
Aaron France
Aaron Jacobs
+Aaron Jensen
Aaron Kemp
Aaron Patterson
Aaron Stein
@@ -71,9 +72,11 @@ Ahmet Alp Balkan
Ahmet Soormally
Ahmy Yulrizka
Ahsun Ahmed
+Aidan Coyle
Aiden Scandella
Ainar Garipov
Aishraj Dahal
+Ajanthan Balachandran
Akhil Indurti
Akihiro Suda
Akshat Kumar
@@ -104,9 +107,11 @@ Alex Buchanan
Alex Carol
Alex Gaynor
Alex Harford
+Alex Hays
Alex Jin
Alex Kohler
Alex Myasoedov
+Alex Opie
Alex Plugaru
Alex Schroeder
Alex Sergeyev
@@ -119,6 +124,7 @@ Alexander F Rødseth
Alexander Greim
Alexander Guz
Alexander Kauer
+Alexander Klauer
Alexander Kucherenko
Alexander Larsson
Alexander Lourier
@@ -150,16 +156,19 @@ Alexey Naidonov
Alexey Neganov
Alexey Palazhchenko
Alexey Semenyuk
+Alexey Vilenskiy
Alexis Hildebrandt
Alexis Hunt
Alexis Imperial-Legrand
Ali Farooq
Ali Rizvi-Santiago
Aliaksandr Valialkin
+Alice Merrick
Alif Rachmawadi
Allan Simon
Allen Li
Alok Menghrajani
+Alwin Doss
Aman Gupta
Amarjeet Anand
Amir Mohammad Saied
@@ -168,6 +177,8 @@ Amrut Joshi
An Long
An Xiao
Anand K. Mistry
+Ananya Saxena
+Anatol Pomozov
Anders Pearson
Anderson Queiroz
André Carvalho
@@ -199,6 +210,7 @@ Andrew G. Morgan
Andrew Gerrand
Andrew Harding
Andrew Jackura
+Andrew Kemm
Andrew Louis
Andrew Lutomirski
Andrew Medvedev
@@ -216,6 +228,7 @@ Andrew Werner
Andrew Wilkins
Andrew Williams
Andrew Z Allen
+Andrey Bokhanko
Andrey Mirtchovski
Andrey Petrov
Andrii Soldatenko
@@ -230,6 +243,7 @@ Andy Maloney
Andy Pan
Andy Walker
Andy Wang
+Andy Williams
Andzej Maciusovic
Anfernee Yongkun Gui
Angelo Bulfone
@@ -274,6 +288,7 @@ Arne Hormann
Arnout Engelen
Aron Nopanen
Artem Alekseev
+Artem Khvastunov
Artem Kolin
Arthur Fabre
Arthur Khashaev
@@ -281,8 +296,10 @@ Artyom Pervukhin
Arvindh Rajesh Tamilmani
Ashish Gandhi
Asim Shankar
+Assel Meher
Atin Malaviya
Ato Araki
+Atsushi Toyama
Audrey Lim
Audrius Butkevicius
Augusto Roman
@@ -291,6 +308,7 @@ Aurélien Rainone
Aurélio A. Heckert
Austin Clements
Avi Flax
+Aviv Klasquin Komissar
awaw fumin
Awn Umar
Axel Wagner
@@ -298,6 +316,7 @@ Ayan George
Ayanamist Yang
Ayke van Laethem
Aymerick Jéhanne
+Ayzat Sadykov
Azat Kaumov
Baiju Muthukadan
Balaram Makam
@@ -308,10 +327,12 @@ Bartosz Grzybowski
Bartosz Oler
Bastian Ike
Ben Burkert
+Ben Cartwright-Cox
Ben Eitzen
Ben Fried
Ben Haines
Ben Hoyt
+Ben Kraft
Ben Laurie
Ben Lubar
Ben Lynn
@@ -319,6 +340,7 @@ Ben Olive
Ben Schwartz
Ben Shi
Ben Toews
+Benjamin Barenblat
Benjamin Black
Benjamin Cable
Benjamin Hsieh
@@ -356,6 +378,7 @@ Bobby Powers
Boqin Qin
Boris Nagaev
Borja Clemente
+Boshi Lian
Brad Burch
Brad Erickson
Brad Fitzpatrick
@@ -368,10 +391,12 @@ Bradford Lamson-Scribner
Bradley Falzon
Brady Catherman
Brady Sullivan
+Branden J. Brown
Brandon Bennett
Brandon Gilmore
Brandon Philips
Brandon Ryan
+Brave Cow
Brayden Cloud
Brendan Daniel Tracey
Brendan O'Dea
@@ -389,6 +414,7 @@ Brian Slesinsky
Brian Smith
Brian Starke
Bryan Alexander
+Bryan Boreham
Bryan C. Mills
Bryan Chan
Bryan Ford
@@ -407,6 +433,7 @@ Carl Mastrangelo
Carl Shapiro
Carlisia Campos
Carlo Alberto Ferraris
+Carlos Alexandro Becker
Carlos Amedee
Carlos Castillo
Carlos Cirello
@@ -422,6 +449,7 @@ Casey Callendrello
Casey Marshall
Catalin Nicutar
Catalin Patulea
+Cathal O'Callaghan
Cedric Staub
Cezar Sá Espinola
Chad Rosier
@@ -434,10 +462,14 @@ Charles Kenney
Charles L. Dorian
Charles Lee
Charles Weill
+Charlotte Brandhorst-Satzkorn
Chauncy Cullitan
+Chen Zhidong
Chen Zhihan
Cherry Zhang
Chew Choon Keat
+Chiawen Chen
+Chirag Sukhala
Cholerae Hu
Chotepud Teo
Chris Ball
@@ -460,6 +492,8 @@ Chris Raynor
Chris Roche
Chris Smith
Chris Stockton
+Chris Taylor
+Chris Waldon
Chris Zou
Christian Alexander
Christian Couder
@@ -467,6 +501,7 @@ Christian Himpel
Christian Muehlhaeuser
Christian Pellegrin
Christian R. Petrin
+Christian Svensson
Christine Hansmann
Christoffer Buchholz
Christoph Blecker
@@ -474,6 +509,7 @@ Christoph Hack
Christopher Cahoon
Christopher Guiney
Christopher Henderson
+Christopher Hlubek
Christopher Koch
Christopher Loessl
Christopher Nelson