diff --git a/doc/asm.html b/doc/asm.html
index 7173d9bd51..d578800086 100644
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -827,10 +827,6 @@ The other codes are ->
(arithmetic right shift),
-The ARM64 port is in an experimental state. -
-
R18
is the "platform register", reserved on the Apple platform.
To prevent accidental misuse, the register is named R18_PLATFORM
.
diff --git a/doc/go1.17.html b/doc/go1.17.html
index 66b4f48b61..4fa30158bb 100644
--- a/doc/go1.17.html
+++ b/doc/go1.17.html
@@ -1132,10 +1132,13 @@ func Foo() bool {
The new Time.UnixMilli
and
- Time.UnixMicro
methods return the number of milliseconds and
- microseconds elapsed since January 1, 1970 UTC respectively.
- The new UnixMilli
and UnixMicro
functions return local Time corresponding to given
- Unix time.
+ Time.UnixMicro
+ methods return the number of milliseconds and microseconds elapsed since
+ January 1, 1970 UTC respectively.
+
+ The new UnixMilli
and
+ UnixMicro
functions
+ return the local Time
corresponding to the given Unix time.
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index 27522ca85e..b20fc8cccc 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -651,7 +651,7 @@ var kinds = []int{
// tflag is documented in reflect/type.go.
//
// tflag values must be kept in sync with copies in:
-// cmd/compile/internal/gc/reflect.go
+// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
// reflect/type.go
// runtime/type.go
diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go
index 095b795d03..a52dd060a0 100644
--- a/src/cmd/compile/internal/types/fmt.go
+++ b/src/cmd/compile/internal/types/fmt.go
@@ -109,14 +109,18 @@ func sconv(s *Sym, verb rune, mode fmtMode) string {
return ""
}
- if s.Name == "_" {
- return "_"
+ q := pkgqual(s.Pkg, verb, mode)
+ if q == "" {
+ return s.Name
}
+
buf := fmtBufferPool.Get().(*bytes.Buffer)
buf.Reset()
defer fmtBufferPool.Put(buf)
- symfmt(buf, s, verb, mode)
+ buf.WriteString(q)
+ buf.WriteByte('.')
+ buf.WriteString(s.Name)
return InternString(buf.Bytes())
}
@@ -128,56 +132,49 @@ func sconv2(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
b.WriteString("")
return
}
- if s.Name == "_" {
- b.WriteString("_")
- return
- }
symfmt(b, s, verb, mode)
}
func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
+ if q := pkgqual(s.Pkg, verb, mode); q != "" {
+ b.WriteString(q)
+ b.WriteByte('.')
+ }
+ b.WriteString(s.Name)
+}
+
+// pkgqual returns the qualifier that should be used for printing
+// symbols from the given package in the given mode.
+// If it returns the empty string, no qualification is needed.
+func pkgqual(pkg *Pkg, verb rune, mode fmtMode) string {
if verb != 'S' {
switch mode {
case fmtGo: // This is for the user
- if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg {
- b.WriteString(s.Name)
- return
+ if pkg == BuiltinPkg || pkg == LocalPkg {
+ return ""
}
// If the name was used by multiple packages, display the full path,
- if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 {
- fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name)
- return
+ if pkg.Name != "" && NumImport[pkg.Name] > 1 {
+ return strconv.Quote(pkg.Path)
}
- b.WriteString(s.Pkg.Name)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
+ return pkg.Name
case fmtDebug:
- b.WriteString(s.Pkg.Name)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
+ return pkg.Name
case fmtTypeIDName:
// dcommontype, typehash
- b.WriteString(s.Pkg.Name)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
+ return pkg.Name
case fmtTypeID:
// (methodsym), typesym, weaksym
- b.WriteString(s.Pkg.Prefix)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
+ return pkg.Prefix
}
}
- b.WriteString(s.Name)
+ return ""
}
// Type
diff --git a/src/cmd/go/internal/lockedfile/lockedfile_filelock.go b/src/cmd/go/internal/lockedfile/lockedfile_filelock.go
index 729df5c681..e4923f6876 100644
--- a/src/cmd/go/internal/lockedfile/lockedfile_filelock.go
+++ b/src/cmd/go/internal/lockedfile/lockedfile_filelock.go
@@ -11,7 +11,6 @@ import (
"io/fs"
"os"
- "cmd/go/internal/fsys"
"cmd/go/internal/lockedfile/internal/filelock"
)
@@ -21,7 +20,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
// calls for Linux and Windows anyway, so it's simpler to use that approach
// consistently.
- f, err := fsys.OpenFile(name, flag&^os.O_TRUNC, perm)
+ f, err := os.OpenFile(name, flag&^os.O_TRUNC, perm)
if err != nil {
return nil, err
}
diff --git a/src/cmd/go/internal/lockedfile/lockedfile_plan9.go b/src/cmd/go/internal/lockedfile/lockedfile_plan9.go
index 3d4b97d78e..979118b10a 100644
--- a/src/cmd/go/internal/lockedfile/lockedfile_plan9.go
+++ b/src/cmd/go/internal/lockedfile/lockedfile_plan9.go
@@ -13,8 +13,6 @@ import (
"os"
"strings"
"time"
-
- "cmd/go/internal/fsys"
)
// Opening an exclusive-use file returns an error.
@@ -59,7 +57,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
// If the file was unpacked or created by some other program, it might not
// have the ModeExclusive bit set. Set it before we call OpenFile, so that we
// can be confident that a successful OpenFile implies exclusive use.
- if fi, err := fsys.Stat(name); err == nil {
+ if fi, err := os.Stat(name); err == nil {
if fi.Mode()&fs.ModeExclusive == 0 {
if err := os.Chmod(name, fi.Mode()|fs.ModeExclusive); err != nil {
return nil, err
@@ -72,7 +70,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
nextSleep := 1 * time.Millisecond
const maxSleep = 500 * time.Millisecond
for {
- f, err := fsys.OpenFile(name, flag, perm|fs.ModeExclusive)
+ f, err := os.OpenFile(name, flag, perm|fs.ModeExclusive)
if err == nil {
return f, nil
}
diff --git a/src/cmd/go/internal/modfetch/codehost/git_test.go b/src/cmd/go/internal/modfetch/codehost/git_test.go
index 89a73baad9..a684fa1a9b 100644
--- a/src/cmd/go/internal/modfetch/codehost/git_test.go
+++ b/src/cmd/go/internal/modfetch/codehost/git_test.go
@@ -8,7 +8,6 @@ import (
"archive/zip"
"bytes"
"flag"
- "fmt"
"internal/testenv"
"io"
"io/fs"
@@ -47,12 +46,6 @@ var altRepos = []string{
var localGitRepo string
func testMain(m *testing.M) int {
- if _, err := exec.LookPath("git"); err != nil {
- fmt.Fprintln(os.Stderr, "skipping because git binary not found")
- fmt.Println("PASS")
- return 0
- }
-
dir, err := os.MkdirTemp("", "gitrepo-test-")
if err != nil {
log.Fatal(err)
@@ -60,23 +53,25 @@ func testMain(m *testing.M) int {
defer os.RemoveAll(dir)
if testenv.HasExternalNetwork() && testenv.HasExec() {
- // Clone gitrepo1 into a local directory.
- // If we use a file:// URL to access the local directory,
- // then git starts up all the usual protocol machinery,
- // which will let us test remote git archive invocations.
- localGitRepo = filepath.Join(dir, "gitrepo2")
- if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
- log.Fatal(err)
- }
- if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
- log.Fatal(err)
+ if _, err := exec.LookPath("git"); err == nil {
+ // Clone gitrepo1 into a local directory.
+ // If we use a file:// URL to access the local directory,
+ // then git starts up all the usual protocol machinery,
+ // which will let us test remote git archive invocations.
+ localGitRepo = filepath.Join(dir, "gitrepo2")
+ if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
+ log.Fatal(err)
+ }
+ if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
+ log.Fatal(err)
+ }
}
}
return m.Run()
}
-func testRepo(remote string) (Repo, error) {
+func testRepo(t *testing.T, remote string) (Repo, error) {
if remote == "localGitRepo" {
// Convert absolute path to file URL. LocalGitRepo will not accept
// Windows absolute paths because they look like a host:path remote.
@@ -87,15 +82,17 @@ func testRepo(remote string) (Repo, error) {
} else {
url = "file:///" + filepath.ToSlash(localGitRepo)
}
+ testenv.MustHaveExecPath(t, "git")
return LocalGitRepo(url)
}
- kind := "git"
+ vcs := "git"
for _, k := range []string{"hg"} {
if strings.Contains(remote, "/"+k+"/") {
- kind = k
+ vcs = k
}
}
- return NewRepo(kind, remote)
+ testenv.MustHaveExecPath(t, vcs)
+ return NewRepo(vcs, remote)
}
var tagsTests = []struct {
@@ -116,7 +113,7 @@ func TestTags(t *testing.T) {
for _, tt := range tagsTests {
f := func(t *testing.T) {
- r, err := testRepo(tt.repo)
+ r, err := testRepo(t, tt.repo)
if err != nil {
t.Fatal(err)
}
@@ -168,7 +165,7 @@ func TestLatest(t *testing.T) {
for _, tt := range latestTests {
f := func(t *testing.T) {
- r, err := testRepo(tt.repo)
+ r, err := testRepo(t, tt.repo)
if err != nil {
t.Fatal(err)
}
@@ -221,7 +218,7 @@ func TestReadFile(t *testing.T) {
for _, tt := range readFileTests {
f := func(t *testing.T) {
- r, err := testRepo(tt.repo)
+ r, err := testRepo(t, tt.repo)
if err != nil {
t.Fatal(err)
}
@@ -412,7 +409,7 @@ func TestReadZip(t *testing.T) {
for _, tt := range readZipTests {
f := func(t *testing.T) {
- r, err := testRepo(tt.repo)
+ r, err := testRepo(t, tt.repo)
if err != nil {
t.Fatal(err)
}
@@ -581,7 +578,7 @@ func TestStat(t *testing.T) {
for _, tt := range statTests {
f := func(t *testing.T) {
- r, err := testRepo(tt.repo)
+ r, err := testRepo(t, tt.repo)
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go
index e40593abae..d3d30d970b 100644
--- a/src/cmd/go/internal/modfetch/fetch.go
+++ b/src/cmd/go/internal/modfetch/fetch.go
@@ -22,6 +22,7 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
+ "cmd/go/internal/fsys"
"cmd/go/internal/lockedfile"
"cmd/go/internal/par"
"cmd/go/internal/robustio"
@@ -416,7 +417,18 @@ func initGoSum() (bool, error) {
goSum.m = make(map[module.Version][]string)
goSum.status = make(map[modSum]modSumStatus)
- data, err := lockedfile.Read(GoSumFile)
+ var (
+ data []byte
+ err error
+ )
+ if actualSumFile, ok := fsys.OverlayPath(GoSumFile); ok {
+ // Don't lock go.sum if it's part of the overlay.
+ // On Plan 9, locking requires chmod, and we don't want to modify any file
+ // in the overlay. See #44700.
+ data, err = os.ReadFile(actualSumFile)
+ } else {
+ data, err = lockedfile.Read(GoSumFile)
+ }
if err != nil && !os.IsNotExist(err) {
return false, err
}
@@ -716,6 +728,9 @@ Outer:
if cfg.BuildMod == "readonly" {
base.Fatalf("go: updates to go.sum needed, disabled by -mod=readonly")
}
+ if _, ok := fsys.OverlayPath(GoSumFile); ok {
+ base.Fatalf("go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay")
+ }
// Make a best-effort attempt to acquire the side lock, only to exclude
// previous versions of the 'go' command from making simultaneous edits.
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index cbc7289afa..a8cbd9fe16 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -71,7 +71,7 @@ type Root int
const (
// AutoRoot is the default for most commands. modload.Init will look for
// a go.mod file in the current directory or any parent. If none is found,
- // modules may be disabled (GO111MODULE=on) or commands may run in a
+ // modules may be disabled (GO111MODULE=auto) or commands may run in a
// limited module mode.
AutoRoot Root = iota
@@ -412,7 +412,16 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
}
gomod := ModFilePath()
- data, err := lockedfile.Read(gomod)
+ var data []byte
+ var err error
+ if gomodActual, ok := fsys.OverlayPath(gomod); ok {
+ // Don't lock go.mod if it's part of the overlay.
+ // On Plan 9, locking requires chmod, and we don't want to modify any file
+ // in the overlay. See #44700.
+ data, err = os.ReadFile(gomodActual)
+ } else {
+ data, err = lockedfile.Read(gomodActual)
+ }
if err != nil {
base.Fatalf("go: %v", err)
}
@@ -1026,6 +1035,13 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements)
}
return
}
+ gomod := ModFilePath()
+ if _, ok := fsys.OverlayPath(gomod); ok {
+ if dirty {
+ base.Fatalf("go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay")
+ }
+ return
+ }
new, err := modFile.Format()
if err != nil {
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index a3a8021c04..771b142b73 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -675,20 +675,6 @@ func DirImportPath(ctx context.Context, dir string) string {
return "."
}
-// TargetPackages returns the list of packages in the target (top-level) module
-// matching pattern, which may be relative to the working directory, under all
-// build tag settings.
-func TargetPackages(ctx context.Context, pattern string) *search.Match {
- // TargetPackages is relative to the main module, so ensure that the main
- // module is a thing that can contain packages.
- LoadModFile(ctx) // Sets Target.
- ModRoot() // Emits an error if Target cannot contain packages.
-
- m := search.NewMatch(pattern)
- matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{Target})
- return m
-}
-
// ImportMap returns the actual package import path
// for an import path found in source code.
// If the given import path does not appear in the source code
@@ -720,29 +706,6 @@ func PackageModule(path string) module.Version {
return pkg.mod
}
-// PackageImports returns the imports for the package named by the import path.
-// Test imports will be returned as well if tests were loaded for the package
-// (i.e., if "all" was loaded or if LoadTests was set and the path was matched
-// by a command line argument). PackageImports will return nil for
-// unknown package paths.
-func PackageImports(path string) (imports, testImports []string) {
- pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
- if !ok {
- return nil, nil
- }
- imports = make([]string, len(pkg.imports))
- for i, p := range pkg.imports {
- imports[i] = p.path
- }
- if pkg.test != nil {
- testImports = make([]string, len(pkg.test.imports))
- for i, p := range pkg.test.imports {
- testImports[i] = p.path
- }
- }
- return imports, testImports
-}
-
// Lookup returns the source directory, import path, and any loading error for
// the package at path as imported from the package in parentDir.
// Lookup requires that one of the Load functions in this package has already
diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go
index 1145ac4ba5..d280945ea6 100644
--- a/src/cmd/go/internal/modload/modfile.go
+++ b/src/cmd/go/internal/modload/modfile.go
@@ -8,6 +8,7 @@ import (
"context"
"errors"
"fmt"
+ "os"
"path/filepath"
"strings"
"sync"
@@ -15,6 +16,7 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
+ "cmd/go/internal/fsys"
"cmd/go/internal/lockedfile"
"cmd/go/internal/modfetch"
"cmd/go/internal/par"
@@ -601,8 +603,16 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
dir = filepath.Join(ModRoot(), dir)
}
gomod := filepath.Join(dir, "go.mod")
-
- data, err := lockedfile.Read(gomod)
+ var data []byte
+ var err error
+ if gomodActual, ok := fsys.OverlayPath(gomod); ok {
+ // Don't lock go.mod if it's part of the overlay.
+ // On Plan 9, locking requires chmod, and we don't want to modify any file
+ // in the overlay. See #44700.
+ data, err = os.ReadFile(gomodActual)
+ } else {
+ data, err = lockedfile.Read(gomodActual)
+ }
if err != nil {
return cached{nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(gomod), err))}
}
diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go
index 6f6c6e8c98..dda9004a9f 100644
--- a/src/cmd/go/internal/modload/query.go
+++ b/src/cmd/go/internal/modload/query.go
@@ -920,8 +920,8 @@ func (e *PackageNotInModuleError) ImportPath() string {
return ""
}
-// ModuleHasRootPackage returns whether module m contains a package m.Path.
-func ModuleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
+// moduleHasRootPackage returns whether module m contains a package m.Path.
+func moduleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
needSum := false
root, isLocal, err := fetch(ctx, m, needSum)
if err != nil {
diff --git a/src/cmd/go/testdata/script/mod_overlay.txt b/src/cmd/go/testdata/script/mod_overlay.txt
index 92e79c725a..86ab04bd3c 100644
--- a/src/cmd/go/testdata/script/mod_overlay.txt
+++ b/src/cmd/go/testdata/script/mod_overlay.txt
@@ -21,7 +21,7 @@ go list -deps -overlay overlay.json .
cd $WORK/gopath/src/get-doesnt-add-dep
cp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
! go get -d -overlay overlay.json .
-stderr 'overlaid files can''t be opened for write'
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
cmp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
# Content of overlaid go.sum is used.
@@ -41,10 +41,10 @@ go mod verify -overlay overlay.json
# attempting to update the file
cp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
! go get -d -overlay overlay.json .
-stderr 'overlaid files can''t be opened for write'
+stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
! go mod tidy -overlay overlay.json
-stderr 'overlaid files can''t be opened for write'
+stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
# -overlay works with -modfile.
@@ -56,7 +56,7 @@ go list -modfile=alternate.mod -overlay overlay.json .
stdout 'found.the/module'
# Even with -modfile, overlaid files can't be opened for write.
! go get -modfile=alternate.mod -overlay overlay.json -d rsc.io/quote
-stderr 'overlaid files can''t be opened for write'
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
# Carving out a module by adding an overlaid go.mod file
cd $WORK/gopath/src/carve
@@ -78,7 +78,7 @@ go list -overlay overlay.json all
stdout ^carve2/nomod$
# Editing go.mod file fails because overlay is read only
! go get -overlay overlay.json -d rsc.io/quote
-stderr 'overlaid files can''t be opened for write'
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
! grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod
# Editing go.mod file succeeds because we use -modfile to redirect to same file
go get -overlay overlay.json -modfile $WORK/overlay/carve2-nomod-go.mod -d rsc.io/quote
diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go
index c41d97706e..629bdcf4ca 100644
--- a/src/cmd/link/internal/ld/decodesym.go
+++ b/src/cmd/link/internal/ld/decodesym.go
@@ -16,12 +16,12 @@ import (
// Decoding the type.* symbols. This has to be in sync with
// ../../runtime/type.go, or more specifically, with what
-// cmd/compile/internal/gc/reflect.go stuffs in these.
+// cmd/compile/internal/reflectdata/reflect.go stuffs in these.
// tflag is documented in reflect/type.go.
//
// tflag values must be kept in sync with copies in:
-// cmd/compile/internal/gc/reflect.go
+// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
// reflect/type.go
// runtime/type.go
diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go
index f529f7c5fc..b1899b0191 100644
--- a/src/internal/reflectlite/type.go
+++ b/src/internal/reflectlite/type.go
@@ -68,7 +68,7 @@ type Type interface {
}
/*
- * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
+ * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
* A few are known to ../runtime/type.go to convey to debuggers.
* They are also known to ../runtime/type.go.
*/
@@ -111,7 +111,7 @@ const (
// available in the memory directly following the rtype value.
//
// tflag values must be kept in sync with copies in:
-// cmd/compile/internal/gc/reflect.go
+// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
// runtime/type.go
type tflag uint8
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 59cdd2bf3e..350ad5def7 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -1846,6 +1846,17 @@ func TestCVE202133195(t *testing.T) {
Target: dnsmessage.MustNewName(".golang.org."),
},
},
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: n,
+ Type: dnsmessage.TypeSRV,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.SRVResource{
+ Target: dnsmessage.MustNewName("good.golang.org."),
+ },
+ },
)
case dnsmessage.TypeMX:
r.Answers = append(r.Answers,
@@ -1860,6 +1871,17 @@ func TestCVE202133195(t *testing.T) {
MX: dnsmessage.MustNewName(".golang.org."),
},
},
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("good.golang.org."),
+ Type: dnsmessage.TypeMX,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.MXResource{
+ MX: dnsmessage.MustNewName("good.golang.org."),
+ },
+ },
)
case dnsmessage.TypeNS:
r.Answers = append(r.Answers,
@@ -1874,6 +1896,17 @@ func TestCVE202133195(t *testing.T) {
NS: dnsmessage.MustNewName(".golang.org."),
},
},
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("good.golang.org."),
+ Type: dnsmessage.TypeNS,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.NSResource{
+ NS: dnsmessage.MustNewName("good.golang.org."),
+ },
+ },
)
case dnsmessage.TypePTR:
r.Answers = append(r.Answers,
@@ -1888,6 +1921,17 @@ func TestCVE202133195(t *testing.T) {
PTR: dnsmessage.MustNewName(".golang.org."),
},
},
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("good.golang.org."),
+ Type: dnsmessage.TypePTR,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.PTRResource{
+ PTR: dnsmessage.MustNewName("good.golang.org."),
+ },
+ },
)
}
return r, nil
@@ -1903,59 +1947,139 @@ func TestCVE202133195(t *testing.T) {
defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
testHookHostsPath = "testdata/hosts"
- _, err := r.LookupCNAME(context.Background(), "golang.org")
- if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err, expected)
- }
- _, err = LookupCNAME("golang.org")
- if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err, expected)
+ tests := []struct {
+ name string
+ f func(*testing.T)
+ }{
+ {
+ name: "CNAME",
+ f: func(t *testing.T) {
+ expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+ _, err := r.LookupCNAME(context.Background(), "golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ _, err = LookupCNAME("golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ },
+ },
+ {
+ name: "SRV (bad record)",
+ f: func(t *testing.T) {
+ expected := []*SRV{
+ {
+ Target: "good.golang.org.",
+ },
+ }
+ expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+ _, records, err := r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ _, records, err = LookupSRV("target", "tcp", "golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Errorf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ },
+ },
+ {
+ name: "SRV (bad header)",
+ f: func(t *testing.T) {
+ _, _, err := r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
+ if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
+ }
+ _, _, err = LookupSRV("hdr", "tcp", "golang.org.")
+ if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
+ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
+ }
+ },
+ },
+ {
+ name: "MX",
+ f: func(t *testing.T) {
+ expected := []*MX{
+ {
+ Host: "good.golang.org.",
+ },
+ }
+ expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+ records, err := r.LookupMX(context.Background(), "golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ records, err = LookupMX("golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ },
+ },
+ {
+ name: "NS",
+ f: func(t *testing.T) {
+ expected := []*NS{
+ {
+ Host: "good.golang.org.",
+ },
+ }
+ expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+ records, err := r.LookupNS(context.Background(), "golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ records, err = LookupNS("golang.org")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ },
+ },
+ {
+ name: "Addr",
+ f: func(t *testing.T) {
+ expected := []string{"good.golang.org."}
+ expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "192.0.2.42"}
+ records, err := r.LookupAddr(context.Background(), "192.0.2.42")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ records, err = LookupAddr("192.0.2.42")
+ if err.Error() != expectedErr.Error() {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if !reflect.DeepEqual(records, expected) {
+ t.Error("Unexpected record set")
+ }
+ },
+ },
}
- _, _, err = r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
- if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
- }
- _, _, err = LookupSRV("target", "tcp", "golang.org")
- if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
+ for _, tc := range tests {
+ t.Run(tc.name, tc.f)
}
- _, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
- if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
- t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
- }
- _, _, err = LookupSRV("hdr", "tcp", "golang.org.")
- if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
- t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
- }
-
- _, err = r.LookupMX(context.Background(), "golang.org")
- if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("Resolver.LookupMX returned unexpected error, got %q, want %q", err, expected)
- }
- _, err = LookupMX("golang.org")
- if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("LookupMX returned unexpected error, got %q, want %q", err, expected)
- }
-
- _, err = r.LookupNS(context.Background(), "golang.org")
- if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("Resolver.LookupNS returned unexpected error, got %q, want %q", err, expected)
- }
- _, err = LookupNS("golang.org")
- if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("LookupNS returned unexpected error, got %q, want %q", err, expected)
- }
-
- _, err = r.LookupAddr(context.Background(), "192.0.2.42")
- if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err, expected)
- }
- _, err = LookupAddr("192.0.2.42")
- if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
- t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err, expected)
- }
}
func TestNullMX(t *testing.T) {
diff --git a/src/net/lookup.go b/src/net/lookup.go
index b5af3a0f86..d350ef7fc0 100644
--- a/src/net/lookup.go
+++ b/src/net/lookup.go
@@ -424,7 +424,7 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error)
return "", err
}
if !isDomainName(cname) {
- return "", &DNSError{Err: "CNAME target is invalid", Name: host}
+ return "", &DNSError{Err: errMalformedDNSRecordsDetail, Name: host}
}
return cname, nil
}
@@ -440,7 +440,9 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error)
// and proto are empty strings, LookupSRV looks up name directly.
//
// The returned service names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
}
@@ -456,7 +458,9 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
// and proto are empty strings, LookupSRV looks up name directly.
//
// The returned service names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
if err != nil {
@@ -465,21 +469,28 @@ func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (
if cname != "" && !isDomainName(cname) {
return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
}
+ filteredAddrs := make([]*SRV, 0, len(addrs))
for _, addr := range addrs {
if addr == nil {
continue
}
if !isDomainName(addr.Target) {
- return "", nil, &DNSError{Err: "SRV target is invalid", Name: name}
+ continue
}
+ filteredAddrs = append(filteredAddrs, addr)
}
- return cname, addrs, nil
+ if len(addrs) != len(filteredAddrs) {
+ return cname, filteredAddrs, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
+ }
+ return cname, filteredAddrs, nil
}
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
//
// The returned mail server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
//
// LookupMX uses context.Background internally; to specify the context, use
// Resolver.LookupMX.
@@ -490,12 +501,15 @@ func LookupMX(name string) ([]*MX, error) {
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
//
// The returned mail server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
records, err := r.lookupMX(ctx, name)
if err != nil {
return nil, err
}
+ filteredMX := make([]*MX, 0, len(records))
for _, mx := range records {
if mx == nil {
continue
@@ -503,16 +517,22 @@ func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
// Bypass the hostname validity check for targets which contain only a dot,
// as this is used to represent a 'Null' MX record.
if mx.Host != "." && !isDomainName(mx.Host) {
- return nil, &DNSError{Err: "MX target is invalid", Name: name}
+ continue
}
+ filteredMX = append(filteredMX, mx)
}
- return records, nil
+ if len(records) != len(filteredMX) {
+ return filteredMX, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
+ }
+ return filteredMX, nil
}
// LookupNS returns the DNS NS records for the given domain name.
//
// The returned name server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
//
// LookupNS uses context.Background internally; to specify the context, use
// Resolver.LookupNS.
@@ -523,21 +543,28 @@ func LookupNS(name string) ([]*NS, error) {
// LookupNS returns the DNS NS records for the given domain name.
//
// The returned name server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
records, err := r.lookupNS(ctx, name)
if err != nil {
return nil, err
}
+ filteredNS := make([]*NS, 0, len(records))
for _, ns := range records {
if ns == nil {
continue
}
if !isDomainName(ns.Host) {
- return nil, &DNSError{Err: "NS target is invalid", Name: name}
+ continue
}
+ filteredNS = append(filteredNS, ns)
}
- return records, nil
+ if len(records) != len(filteredNS) {
+ return filteredNS, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
+ }
+ return filteredNS, nil
}
// LookupTXT returns the DNS TXT records for the given domain name.
@@ -557,7 +584,8 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error)
// of names mapping to that address.
//
// The returned names are validated to be properly formatted presentation-format
-// domain names.
+// domain names. If the response contains invalid names, those records are filtered
+// out and an error will be returned alongside the the remaining results, if any.
//
// When using the host C library resolver, at most one result will be
// returned. To bypass the host resolver, use a custom Resolver.
@@ -572,16 +600,26 @@ func LookupAddr(addr string) (names []string, err error) {
// of names mapping to that address.
//
// The returned names are validated to be properly formatted presentation-format
-// domain names.
+// domain names. If the response contains invalid names, those records are filtered
+// out and an error will be returned alongside the the remaining results, if any.
func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
names, err := r.lookupAddr(ctx, addr)
if err != nil {
return nil, err
}
+ filteredNames := make([]string, 0, len(names))
for _, name := range names {
- if !isDomainName(name) {
- return nil, &DNSError{Err: "PTR target is invalid", Name: addr}
+ if isDomainName(name) {
+ filteredNames = append(filteredNames, name)
}
}
- return names, nil
+ if len(names) != len(filteredNames) {
+ return filteredNames, &DNSError{Err: errMalformedDNSRecordsDetail, Name: addr}
+ }
+ return filteredNames, nil
}
+
+// errMalformedDNSRecordsDetail is the DNSError detail which is returned when a Resolver.Lookup...
+// method recieves DNS records which contain invalid DNS names. This may be returned alongside
+// results which have had the malformed records filtered out.
+var errMalformedDNSRecordsDetail = "DNS response contained records which contain invalid names"
diff --git a/src/reflect/type.go b/src/reflect/type.go
index e119354af4..278426da09 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -229,7 +229,7 @@ type Type interface {
// See https://golang.org/issue/4876 for more details.
/*
- * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
+ * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
* A few are known to ../runtime/type.go to convey to debuggers.
* They are also known to ../runtime/type.go.
*/
@@ -272,7 +272,7 @@ const (
// available in the memory directly following the rtype value.
//
// tflag values must be kept in sync with copies in:
-// cmd/compile/internal/gc/reflect.go
+// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
// runtime/type.go
type tflag uint8
@@ -1911,7 +1911,7 @@ func MapOf(key, elem Type) Type {
// Make a map type.
// Note: flag values must match those used in the TMAP case
- // in ../cmd/compile/internal/gc/reflect.go:writeType.
+ // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
mt := **(**mapType)(unsafe.Pointer(&imap))
mt.str = resolveReflectName(newName(s, "", false))
@@ -2842,7 +2842,7 @@ func runtimeStructField(field StructField) (structField, string) {
// typeptrdata returns the length in bytes of the prefix of t
// containing pointer data. Anything after this offset is scalar data.
-// keep in sync with ../cmd/compile/internal/gc/reflect.go
+// keep in sync with ../cmd/compile/internal/reflectdata/reflect.go
func typeptrdata(t *rtype) uintptr {
switch t.Kind() {
case Struct:
@@ -2866,7 +2866,7 @@ func typeptrdata(t *rtype) uintptr {
}
}
-// See cmd/compile/internal/gc/reflect.go for derivation of constant.
+// See cmd/compile/internal/reflectdata/reflect.go for derivation of constant.
const maxPtrmaskBytes = 2048
// ArrayOf returns the array type with the given length and element type.
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 5795929301..d557ee8a3e 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -895,7 +895,7 @@ type funcinl struct {
// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
-// ../cmd/compile/internal/gc/reflect.go:/^func.WriteTabs.
+// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs.
type itab struct {
inter *interfacetype
_type *_type
diff --git a/src/runtime/select.go b/src/runtime/select.go
index 74f0c29194..ee1f95ffa9 100644
--- a/src/runtime/select.go
+++ b/src/runtime/select.go
@@ -16,7 +16,7 @@ const debugSelect = false
// Select case descriptor.
// Known to compiler.
-// Changes here must also be made in src/cmd/internal/gc/select.go's scasetype.
+// Changes here must also be made in src/cmd/compile/internal/walk/select.go's scasetype.
type scase struct {
c *hchan // chan
elem unsafe.Pointer // data element
diff --git a/src/runtime/type.go b/src/runtime/type.go
index 52e65a3bd2..ad01d5095e 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -14,7 +14,7 @@ import (
// tflag is documented in reflect/type.go.
//
// tflag values must be kept in sync with copies in:
-// cmd/compile/internal/gc/reflect.go
+// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
// reflect/type.go
// internal/reflectlite/type.go
@@ -28,7 +28,7 @@ const (
)
// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,
-// ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and
+// ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and
// ../reflect/type.go:/^type.rtype.
// ../internal/reflectlite/type.go:/^type.rtype.
type _type struct {
@@ -386,7 +386,7 @@ type maptype struct {
}
// Note: flag values must match those used in the TMAP case
-// in ../cmd/compile/internal/gc/reflect.go:writeType.
+// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself
return mt.flags&1 != 0
}
diff --git a/test/fixedbugs/issue47087.dir/a.go b/test/fixedbugs/issue47087.dir/a.go
new file mode 100644
index 0000000000..6093092ace
--- /dev/null
+++ b/test/fixedbugs/issue47087.dir/a.go
@@ -0,0 +1,9 @@
+// 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 a
+
+func F() interface{} { return struct{ _ []int }{} }
+
+var X = F()
diff --git a/test/fixedbugs/issue47087.dir/b.go b/test/fixedbugs/issue47087.dir/b.go
new file mode 100644
index 0000000000..8f96d25a12
--- /dev/null
+++ b/test/fixedbugs/issue47087.dir/b.go
@@ -0,0 +1,9 @@
+// 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
+
+func F() interface{} { return struct{ _ []int }{} }
+
+var X = F()
diff --git a/test/fixedbugs/issue47087.dir/main.go b/test/fixedbugs/issue47087.dir/main.go
new file mode 100644
index 0000000000..ccd0891a61
--- /dev/null
+++ b/test/fixedbugs/issue47087.dir/main.go
@@ -0,0 +1,19 @@
+// 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 main
+
+import (
+ "a"
+ "b"
+)
+
+func main() {
+ if a.F() == b.F() {
+ panic("FAIL")
+ }
+ if a.X == b.X {
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue47087.go b/test/fixedbugs/issue47087.go
new file mode 100644
index 0000000000..40df49f83b
--- /dev/null
+++ b/test/fixedbugs/issue47087.go
@@ -0,0 +1,7 @@
+// rundir
+
+// 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 ignored