summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-06-10 12:37:34 -0700
committerIan Lance Taylor <iant@golang.org>2021-06-10 14:41:23 -0700
commitee52bf609bac45b3c251858a69071262f46ee89c (patch)
tree4c079eab4884dc9c32e6f62fe9e2f0ff0d784306 /libgo
parent00d07ec6e12451acc7a290cd93be03bed50cb666 (diff)
libgo: update to Go1.16.5 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/326772
Diffstat (limited to 'libgo')
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/VERSION2
-rw-r--r--libgo/go/archive/zip/reader.go64
-rw-r--r--libgo/go/archive/zip/reader_test.go115
-rw-r--r--libgo/go/archive/zip/testdata/subdir.zipbin0 -> 428 bytes
-rw-r--r--libgo/go/cmd/go/internal/modcmd/download.go32
-rw-r--r--libgo/go/cmd/go/internal/modcmd/tidy.go2
-rw-r--r--libgo/go/cmd/go/internal/modload/buildlist.go30
-rw-r--r--libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_download.txt36
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_get_trailing_slash.txt10
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_query.txt5
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_readonly.txt8
-rw-r--r--libgo/go/go.mod2
-rw-r--r--libgo/go/golang.org/x/net/http/httpguts/httplex.go10
-rw-r--r--libgo/go/math/big/ratconv.go15
-rw-r--r--libgo/go/math/big/ratconv_test.go25
-rw-r--r--libgo/go/net/dnsclient_unix_test.go158
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go22
-rw-r--r--libgo/go/net/http/httputil/reverseproxy_test.go63
-rw-r--r--libgo/go/net/http/transport_test.go8
-rw-r--r--libgo/go/net/lookup.go111
-rw-r--r--libgo/go/os/signal/signal_test.go42
-rw-r--r--libgo/go/runtime/pprof/pprof_test.go3
-rw-r--r--libgo/go/runtime/proc.go26
-rw-r--r--libgo/go/runtime/runtime2.go7
-rw-r--r--libgo/go/runtime/sigqueue.go2
-rw-r--r--libgo/go/time/zoneinfo.go27
-rw-r--r--libgo/go/time/zoneinfo_read.go44
-rw-r--r--libgo/go/time/zoneinfo_test.go37
-rw-r--r--libgo/go/vendor/modules.txt2
31 files changed, 781 insertions, 131 deletions
diff --git a/libgo/MERGE b/libgo/MERGE
index 81cd0623486..ac842716022 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-9baddd3f21230c55f0ad2a10f5f20579dcf0a0bb
+7677616a263e8ded606cc8297cb67ddc667a876e
The first line of this file holds the git revision number of the
last merge done from the master library sources.
diff --git a/libgo/VERSION b/libgo/VERSION
index e592dfd1338..e336ec201bf 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.16.3
+go1.16.5
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index c288ad965bc..ddef2b7b5a5 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -99,7 +99,15 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
return err
}
z.r = r
- z.File = make([]*File, 0, end.directoryRecords)
+ // Since the number of directory records is not validated, it is not
+ // safe to preallocate z.File without first checking that the specified
+ // number of files is reasonable, since a malformed archive may
+ // indicate it contains up to 1 << 128 - 1 files. Since each file has a
+ // header which will be _at least_ 30 bytes we can safely preallocate
+ // if (data size / 30) >= end.directoryRecords.
+ if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
+ z.File = make([]*File, 0, end.directoryRecords)
+ }
z.Comment = end.comment
rs := io.NewSectionReader(r, 0, size)
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
@@ -628,10 +636,11 @@ func (b *readBuf) sub(n int) readBuf {
}
// A fileListEntry is a File and its ename.
-// If file == nil, the fileListEntry describes a directory, without metadata.
+// If file == nil, the fileListEntry describes a directory without metadata.
type fileListEntry struct {
- name string
- file *File // nil for directories
+ name string
+ file *File
+ isDir bool
}
type fileInfoDirEntry interface {
@@ -640,20 +649,26 @@ type fileInfoDirEntry interface {
}
func (e *fileListEntry) stat() fileInfoDirEntry {
- if e.file != nil {
+ if !e.isDir {
return headerFileInfo{&e.file.FileHeader}
}
return e
}
// Only used for directories.
-func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
-func (f *fileListEntry) Size() int64 { return 0 }
-func (f *fileListEntry) ModTime() time.Time { return time.Time{} }
-func (f *fileListEntry) Mode() fs.FileMode { return fs.ModeDir | 0555 }
-func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
-func (f *fileListEntry) IsDir() bool { return true }
-func (f *fileListEntry) Sys() interface{} { return nil }
+func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
+func (f *fileListEntry) Size() int64 { return 0 }
+func (f *fileListEntry) Mode() fs.FileMode { return fs.ModeDir | 0555 }
+func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
+func (f *fileListEntry) IsDir() bool { return true }
+func (f *fileListEntry) Sys() interface{} { return nil }
+
+func (f *fileListEntry) ModTime() time.Time {
+ if f.file == nil {
+ return time.Time{}
+ }
+ return f.file.FileHeader.Modified.UTC()
+}
func (f *fileListEntry) Info() (fs.FileInfo, error) { return f, nil }
@@ -673,15 +688,32 @@ func toValidName(name string) string {
func (r *Reader) initFileList() {
r.fileListOnce.Do(func() {
dirs := make(map[string]bool)
+ knownDirs := make(map[string]bool)
for _, file := range r.File {
+ isDir := len(file.Name) > 0 && file.Name[len(file.Name)-1] == '/'
name := toValidName(file.Name)
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
dirs[dir] = true
}
- r.fileList = append(r.fileList, fileListEntry{name, file})
+ entry := fileListEntry{
+ name: name,
+ file: file,
+ isDir: isDir,
+ }
+ r.fileList = append(r.fileList, entry)
+ if isDir {
+ knownDirs[name] = true
+ }
}
for dir := range dirs {
- r.fileList = append(r.fileList, fileListEntry{dir + "/", nil})
+ if !knownDirs[dir] {
+ entry := fileListEntry{
+ name: dir,
+ file: nil,
+ isDir: true,
+ }
+ r.fileList = append(r.fileList, entry)
+ }
}
sort.Slice(r.fileList, func(i, j int) bool { return fileEntryLess(r.fileList[i].name, r.fileList[j].name) })
@@ -705,7 +737,7 @@ func (r *Reader) Open(name string) (fs.File, error) {
if e == nil || !fs.ValidPath(name) {
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
}
- if e.file == nil || strings.HasSuffix(e.file.Name, "/") {
+ if e.isDir {
return &openDir{e, r.openReadDir(name), 0}, nil
}
rc, err := e.file.Open()
@@ -730,7 +762,7 @@ func split(name string) (dir, elem string, isDir bool) {
return name[:i], name[i+1:], isDir
}
-var dotFile = &fileListEntry{name: "./"}
+var dotFile = &fileListEntry{name: "./", isDir: true}
func (r *Reader) openLookup(name string) *fileListEntry {
if name == "." {
diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go
index 5faf1f49b51..471be27bb10 100644
--- a/libgo/go/archive/zip/reader_test.go
+++ b/libgo/go/archive/zip/reader_test.go
@@ -1073,12 +1073,62 @@ func TestIssue12449(t *testing.T) {
}
func TestFS(t *testing.T) {
- z, err := OpenReader("testdata/unix.zip")
+ for _, test := range []struct {
+ file string
+ want []string
+ }{
+ {
+ "testdata/unix.zip",
+ []string{"hello", "dir/bar", "readonly"},
+ },
+ {
+ "testdata/subdir.zip",
+ []string{"a/b/c"},
+ },
+ } {
+ t.Run(test.file, func(t *testing.T) {
+ t.Parallel()
+ z, err := OpenReader(test.file)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer z.Close()
+ if err := fstest.TestFS(z, test.want...); err != nil {
+ t.Error(err)
+ }
+ })
+ }
+}
+
+func TestFSModTime(t *testing.T) {
+ t.Parallel()
+ z, err := OpenReader("testdata/subdir.zip")
if err != nil {
t.Fatal(err)
}
- if err := fstest.TestFS(z, "hello", "dir/bar", "dir/empty", "readonly"); err != nil {
- t.Fatal(err)
+ defer z.Close()
+
+ for _, test := range []struct {
+ name string
+ want time.Time
+ }{
+ {
+ "a",
+ time.Date(2021, 4, 19, 12, 29, 56, 0, timeZone(-7*time.Hour)).UTC(),
+ },
+ {
+ "a/b/c",
+ time.Date(2021, 4, 19, 12, 29, 59, 0, timeZone(-7*time.Hour)).UTC(),
+ },
+ } {
+ fi, err := fs.Stat(z, test.name)
+ if err != nil {
+ t.Errorf("%s: %v", test.name, err)
+ continue
+ }
+ if got := fi.ModTime(); !got.Equal(test.want) {
+ t.Errorf("%s: got modtime %v, want %v", test.name, got, test.want)
+ }
}
}
@@ -1116,3 +1166,62 @@ func TestCVE202127919(t *testing.T) {
t.Errorf("Error reading file: %v", err)
}
}
+
+func TestCVE202133196(t *testing.T) {
+ // Archive that indicates it has 1 << 128 -1 files,
+ // this would previously cause a panic due to attempting
+ // to allocate a slice with 1 << 128 -1 elements.
+ data := []byte{
+ 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
+ 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
+ 0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
+ 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
+ 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
+ 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0x00,
+ }
+ _, err := NewReader(bytes.NewReader(data), int64(len(data)))
+ if err != ErrFormat {
+ t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
+ }
+
+ // Also check that an archive containing a handful of empty
+ // files doesn't cause an issue
+ b := bytes.NewBuffer(nil)
+ w := NewWriter(b)
+ for i := 0; i < 5; i++ {
+ _, err := w.Create("")
+ if err != nil {
+ t.Fatalf("Writer.Create failed: %s", err)
+ }
+ }
+ if err := w.Close(); err != nil {
+ t.Fatalf("Writer.Close failed: %s", err)
+ }
+ r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
+ if err != nil {
+ t.Fatalf("NewReader failed: %s", err)
+ }
+ if len(r.File) != 5 {
+ t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
+ }
+}
diff --git a/libgo/go/archive/zip/testdata/subdir.zip b/libgo/go/archive/zip/testdata/subdir.zip
new file mode 100644
index 00000000000..324d06b48d1
--- /dev/null
+++ b/libgo/go/archive/zip/testdata/subdir.zip
Binary files differ
diff --git a/libgo/go/cmd/go/internal/modcmd/download.go b/libgo/go/cmd/go/internal/modcmd/download.go
index e7d3d869cbc..a602bb9bbe9 100644
--- a/libgo/go/cmd/go/internal/modcmd/download.go
+++ b/libgo/go/cmd/go/internal/modcmd/download.go
@@ -86,9 +86,11 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
if !modload.HasModRoot() && len(args) == 0 {
base.Fatalf("go mod download: no modules specified (see 'go help mod download')")
}
- if len(args) == 0 {
+ haveExplicitArgs := len(args) > 0
+ if !haveExplicitArgs {
args = []string{"all"}
- } else if modload.HasModRoot() {
+ }
+ if modload.HasModRoot() {
modload.LoadModFile(ctx) // to fill Target
targetAtUpgrade := modload.Target.Path + "@upgrade"
targetAtPatch := modload.Target.Path + "@patch"
@@ -137,7 +139,20 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
listRetractions := false
type token struct{}
sem := make(chan token, runtime.GOMAXPROCS(0))
- for _, info := range modload.ListModules(ctx, args, listU, listVersions, listRetractions) {
+ infos := modload.ListModules(ctx, args, listU, listVersions, listRetractions)
+ if !haveExplicitArgs {
+ // 'go mod download' is sometimes run without arguments to pre-populate
+ // the module cache. It may fetch modules that aren't needed to build
+ // packages in the main mdoule. This is usually not intended, so don't save
+ // sums for downloaded modules (golang.org/issue/45332).
+ // TODO(golang.org/issue/45551): For now, save sums needed to load the
+ // build list (same as 1.15 behavior). In the future, report an error if
+ // go.mod or go.sum need to be updated after loading the build list.
+ modload.WriteGoMod()
+ modload.DisallowWriteGoMod()
+ }
+
+ for _, info := range infos {
if info.Replace != nil {
info = info.Replace
}
@@ -187,6 +202,13 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
base.ExitIfErrors()
}
- // Update go.mod and especially go.sum if needed.
- modload.WriteGoMod()
+ // If there were explicit arguments, update go.mod and especially go.sum.
+ // 'go mod download mod@version' is a useful way to add a sum without using
+ // 'go get mod@version', which may have other side effects. We print this in
+ // some error message hints.
+ //
+ // Don't save sums for 'go mod download' without arguments; see comment above.
+ if haveExplicitArgs {
+ modload.WriteGoMod()
+ }
}
diff --git a/libgo/go/cmd/go/internal/modcmd/tidy.go b/libgo/go/cmd/go/internal/modcmd/tidy.go
index 8bc9ed50bed..67f90b123c3 100644
--- a/libgo/go/cmd/go/internal/modcmd/tidy.go
+++ b/libgo/go/cmd/go/internal/modcmd/tidy.go
@@ -61,6 +61,8 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
modload.ForceUseModules = true
modload.RootMode = modload.NeedRoot
+ modload.CheckTidyVersion(ctx, tidyE)
+
modload.LoadPackages(ctx, modload.PackageOpts{
Tags: imports.AnyTags(),
ResolveMissingImports: true,
diff --git a/libgo/go/cmd/go/internal/modload/buildlist.go b/libgo/go/cmd/go/internal/modload/buildlist.go
index 45f220a6ee6..0ed985384d8 100644
--- a/libgo/go/cmd/go/internal/modload/buildlist.go
+++ b/libgo/go/cmd/go/internal/modload/buildlist.go
@@ -11,10 +11,13 @@ import (
"cmd/go/internal/mvs"
"context"
"fmt"
+ "go/build"
"os"
"strings"
+ "golang.org/x/mod/modfile"
"golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
)
// buildList is the list of modules to use for building packages.
@@ -226,6 +229,33 @@ func ReloadBuildList() []module.Version {
return capVersionSlice(buildList)
}
+// CheckTidyVersion reports an error to stderr if the Go version indicated by
+// the go.mod file is not supported by this version of the 'go' command.
+//
+// If allowError is false, such an error terminates the program.
+func CheckTidyVersion(ctx context.Context, allowError bool) {
+ LoadModFile(ctx)
+ if index.goVersionV == "" {
+ return
+ }
+
+ tags := build.Default.ReleaseTags
+ maxGo := tags[len(tags)-1]
+ if !strings.HasPrefix(maxGo, "go") || !modfile.GoVersionRE.MatchString(maxGo[2:]) {
+ base.Fatalf("go: unrecognized go version %q", maxGo)
+ }
+ max := maxGo[2:]
+
+ if semver.Compare(index.goVersionV, "v"+max) > 0 {
+ have := index.goVersionV[1:]
+ if allowError {
+ fmt.Fprintf(os.Stderr, "go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", have, max)
+ } else {
+ base.Fatalf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", have, max)
+ }
+ }
+}
+
// TidyBuildList trims the build list to the minimal requirements needed to
// retain the same versions of all packages from the preceding call to
// LoadPackages.
diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt
index 00b71bf0d59..7982cccea10 100644
--- a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt
+++ b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt
@@ -5,7 +5,7 @@ module "rsc.io/sampler"
require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c
-- .info --
-{"Version":"v1.2.1","Name":"cac3af4f8a0ab40054fa6f8d423108a63a1255bb","Short":"cac3af4f8a0a","Time":"2018-02-13T18:16:22Z"}EOF
+{"Version":"v1.2.1","Name":"cac3af4f8a0ab40054fa6f8d423108a63a1255bb","Short":"cac3af4f8a0a","Time":"2018-02-13T18:16:22Z"}
-- hello.go --
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/libgo/go/cmd/go/testdata/script/mod_download.txt b/libgo/go/cmd/go/testdata/script/mod_download.txt
index 8a9faffe4e0..c2b72b2a02c 100644
--- a/libgo/go/cmd/go/testdata/script/mod_download.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_download.txt
@@ -107,13 +107,28 @@ stderr '^go mod download: skipping argument m that resolves to the main module\n
! go mod download m@latest
stderr '^go mod download: m@latest: malformed module path "m": missing dot in first path element$'
-# download updates go.mod and populates go.sum
+# download without arguments updates go.mod and go.sum after loading the
+# build list, but does not save sums for downloaded zips.
cd update
+cp go.mod.orig go.mod
! exists go.sum
go mod download
+cmp go.mod.update go.mod
+cmp go.sum.update go.sum
+cp go.mod.orig go.mod
+rm go.sum
+
+# download with arguments (even "all") does update go.mod and go.sum.
+go mod download rsc.io/sampler
+cmp go.mod.update go.mod
grep '^rsc.io/sampler v1.3.0 ' go.sum
-go list -m rsc.io/sampler
-stdout '^rsc.io/sampler v1.3.0$'
+cp go.mod.orig go.mod
+rm go.sum
+
+go mod download all
+cmp go.mod.update go.mod
+grep '^rsc.io/sampler v1.3.0 ' go.sum
+cd ..
# allow go mod download without go.mod
env GO111MODULE=auto
@@ -131,7 +146,7 @@ stderr 'get '$GOPROXY
-- go.mod --
module m
--- update/go.mod --
+-- update/go.mod.orig --
module m
go 1.16
@@ -140,3 +155,16 @@ require (
rsc.io/quote v1.5.2
rsc.io/sampler v1.2.1 // older version than in build list
)
+-- update/go.mod.update --
+module m
+
+go 1.16
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/sampler v1.3.0 // older version than in build list
+)
+-- update/go.sum.update --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_trailing_slash.txt b/libgo/go/cmd/go/testdata/script/mod_get_trailing_slash.txt
index 3b38d8ba7d3..c5366935379 100644
--- a/libgo/go/cmd/go/testdata/script/mod_get_trailing_slash.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_get_trailing_slash.txt
@@ -1,6 +1,3 @@
-# Populate go.sum
-go mod download
-
# go list should succeed to load a package ending with ".go" if the path does
# not correspond to an existing local file. Listing a pattern ending with
# ".go/" should try to list a package regardless of whether a file exists at the
@@ -31,3 +28,10 @@ module m
go 1.13
require example.com/dotgo.go v1.0.0
+-- go.sum --
+example.com/dotgo.go v1.0.0 h1:XKJfs0V8x2PvY2tX8bJBCEbCDLnt15ma2onwhVpew/I=
+example.com/dotgo.go v1.0.0/go.mod h1:Qi6z/X3AC5vHiuMt6HF2ICx3KhIBGrMdrA7YoPDKqR0=
+-- use.go --
+package use
+
+import _ "example.com/dotgo.go"
diff --git a/libgo/go/cmd/go/testdata/script/mod_query.txt b/libgo/go/cmd/go/testdata/script/mod_query.txt
index e10185709d9..a75f86ed7c5 100644
--- a/libgo/go/cmd/go/testdata/script/mod_query.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_query.txt
@@ -1,9 +1,7 @@
env GO111MODULE=on
-# Populate go.sum.
# TODO(golang.org/issue/41297): we shouldn't need go.sum. None of the commands
# below depend on the build list.
-go mod download
go list -m -versions rsc.io/quote
stdout '^rsc.io/quote v1.0.0 v1.1.0 v1.2.0 v1.2.1 v1.3.0 v1.4.0 v1.5.0 v1.5.1 v1.5.2 v1.5.3-pre1$'
@@ -36,6 +34,9 @@ stdout 'no matching versions for query ">v1.5.3"'
module x
require rsc.io/quote v1.0.0
+-- go.sum --
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
-- use.go --
package use
diff --git a/libgo/go/cmd/go/testdata/script/mod_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_readonly.txt
index 176be729679..d05ad2a3174 100644
--- a/libgo/go/cmd/go/testdata/script/mod_readonly.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_readonly.txt
@@ -89,7 +89,7 @@ stderr '^no required module provides package rsc.io/quote; to add it:\n\tgo get
-- go.mod --
module m
-go 1.20
+go 1.16
-- x.go --
package x
@@ -104,7 +104,7 @@ require (
-- go.mod.redundant --
module m
-go 1.20
+go 1.16
require (
rsc.io/quote v1.5.2
@@ -114,7 +114,7 @@ require (
-- go.mod.indirect --
module m
-go 1.20
+go 1.16
require (
rsc.io/quote v1.5.2 // indirect
@@ -124,7 +124,7 @@ require (
-- go.mod.untidy --
module m
-go 1.20
+go 1.16
require (
rsc.io/sampler v1.3.0 // indirect
diff --git a/libgo/go/go.mod b/libgo/go/go.mod
index 4ae14eea5cb..798677b68c1 100644
--- a/libgo/go/go.mod
+++ b/libgo/go/go.mod
@@ -4,7 +4,7 @@ go 1.16
require (
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
- golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
+ golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/text v0.3.4 // indirect
)
diff --git a/libgo/go/golang.org/x/net/http/httpguts/httplex.go b/libgo/go/golang.org/x/net/http/httpguts/httplex.go
index e7de24ee64e..c79aa73f28b 100644
--- a/libgo/go/golang.org/x/net/http/httpguts/httplex.go
+++ b/libgo/go/golang.org/x/net/http/httpguts/httplex.go
@@ -137,11 +137,13 @@ func trimOWS(x string) string {
// contains token amongst its comma-separated tokens, ASCII
// case-insensitively.
func headerValueContainsToken(v string, token string) bool {
- v = trimOWS(v)
- if comma := strings.IndexByte(v, ','); comma != -1 {
- return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
+ for comma := strings.IndexByte(v, ','); comma != -1; comma = strings.IndexByte(v, ',') {
+ if tokenEqual(trimOWS(v[:comma]), token) {
+ return true
+ }
+ v = v[comma+1:]
}
- return tokenEqual(v, token)
+ return tokenEqual(trimOWS(v), token)
}
// lowerASCII returns the ASCII lowercase version of b.
diff --git a/libgo/go/math/big/ratconv.go b/libgo/go/math/big/ratconv.go
index 941139e72d1..ac3c8bd11f8 100644
--- a/libgo/go/math/big/ratconv.go
+++ b/libgo/go/math/big/ratconv.go
@@ -51,7 +51,8 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
// An optional base-10 ``e'' or base-2 ``p'' (or their upper-case variants)
// exponent may be provided as well, except for hexadecimal floats which
// only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot
-// be distinguished from a mantissa digit).
+// be distinguished from a mantissa digit). If the exponent's absolute value
+// is too large, the operation may fail.
// The entire string, not just a prefix, must be valid for success. If the
// operation failed, the value of z is undefined but the returned value is nil.
func (z *Rat) SetString(s string) (*Rat, bool) {
@@ -169,6 +170,9 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
if n < 0 {
n = -n
}
+ if n > 1e6 {
+ return nil, false // avoid excessively large exponents
+ }
pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
if exp5 > 0 {
z.a.abs = z.a.abs.mul(z.a.abs, pow5)
@@ -181,15 +185,12 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
}
// apply exp2 contributions
+ if exp2 < -1e7 || exp2 > 1e7 {
+ return nil, false // avoid excessively large exponents
+ }
if exp2 > 0 {
- if int64(uint(exp2)) != exp2 {
- panic("exponent too large")
- }
z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
} else if exp2 < 0 {
- if int64(uint(-exp2)) != -exp2 {
- panic("exponent too large")
- }
z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
}
diff --git a/libgo/go/math/big/ratconv_test.go b/libgo/go/math/big/ratconv_test.go
index ba0d1ba9e11..15d206cb386 100644
--- a/libgo/go/math/big/ratconv_test.go
+++ b/libgo/go/math/big/ratconv_test.go
@@ -589,3 +589,28 @@ func TestIssue31184(t *testing.T) {
}
}
}
+
+func TestIssue45910(t *testing.T) {
+ var x Rat
+ for _, test := range []struct {
+ input string
+ want bool
+ }{
+ {"1e-1000001", false},
+ {"1e-1000000", true},
+ {"1e+1000000", true},
+ {"1e+1000001", false},
+
+ {"0p1000000000000", true},
+ {"1p-10000001", false},
+ {"1p-10000000", true},
+ {"1p+10000000", true},
+ {"1p+10000001", false},
+ {"1.770p02041010010011001001", false}, // test case from issue
+ } {
+ _, got := x.SetString(test.input)
+ if got != test.want {
+ t.Errorf("SetString(%s) got ok = %v; want %v", test.input, got, test.want)
+ }
+ }
+}
diff --git a/libgo/go/net/dnsclient_unix_test.go b/libgo/go/net/dnsclient_unix_test.go
index f57f231d699..3c9ada365c4 100644
--- a/libgo/go/net/dnsclient_unix_test.go
+++ b/libgo/go/net/dnsclient_unix_test.go
@@ -1798,3 +1798,161 @@ func TestPTRandNonPTR(t *testing.T) {
t.Errorf("names = %q; want %q", names, want)
}
}
+
+func TestCVE202133195(t *testing.T) {
+ fake := fakeDNSServer{
+ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+ r := dnsmessage.Message{
+ Header: dnsmessage.Header{
+ ID: q.Header.ID,
+ Response: true,
+ RCode: dnsmessage.RCodeSuccess,
+ RecursionAvailable: true,
+ },
+ Questions: q.Questions,
+ }
+ switch q.Questions[0].Type {
+ case dnsmessage.TypeCNAME:
+ r.Answers = []dnsmessage.Resource{}
+ case dnsmessage.TypeA: // CNAME lookup uses a A/AAAA as a proxy
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.AResource{
+ A: TestAddr,
+ },
+ },
+ )
+ case dnsmessage.TypeSRV:
+ n := q.Questions[0].Name
+ if n.String() == "_hdr._tcp.golang.org." {
+ n = dnsmessage.MustNewName("<html>.golang.org.")
+ }
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: n,
+ Type: dnsmessage.TypeSRV,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.SRVResource{
+ Target: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ case dnsmessage.TypeMX:
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypeMX,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.MXResource{
+ MX: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ case dnsmessage.TypeNS:
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypeNS,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.NSResource{
+ NS: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ case dnsmessage.TypePTR:
+ r.Answers = append(r.Answers,
+ dnsmessage.Resource{
+ Header: dnsmessage.ResourceHeader{
+ Name: dnsmessage.MustNewName("<html>.golang.org."),
+ Type: dnsmessage.TypePTR,
+ Class: dnsmessage.ClassINET,
+ Length: 4,
+ },
+ Body: &dnsmessage.PTRResource{
+ PTR: dnsmessage.MustNewName("<html>.golang.org."),
+ },
+ },
+ )
+ }
+ return r, nil
+ },
+ }
+
+ r := Resolver{PreferGo: true, Dial: fake.DialContext}
+ // Change the default resolver to match our manipulated resolver
+ originalDefault := DefaultResolver
+ DefaultResolver = &r
+ defer func() { DefaultResolver = originalDefault }()
+ // Redirect host file lookups.
+ 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)
+ }
+
+ _, _, 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)
+ }
+
+ _, _, 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)
+ }
+}
diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go
index 4e369580ea8..ccb84562e0a 100644
--- a/libgo/go/net/http/httputil/reverseproxy.go
+++ b/libgo/go/net/http/httputil/reverseproxy.go
@@ -248,22 +248,18 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// important is "Connection" because we want a persistent
// connection, regardless of what the client sent to us.
for _, h := range hopHeaders {
- hv := outreq.Header.Get(h)
- if hv == "" {
- continue
- }
- if h == "Te" && hv == "trailers" {
- // Issue 21096: tell backend applications that
- // care about trailer support that we support
- // trailers. (We do, but we don't go out of
- // our way to advertise that unless the
- // incoming client request thought it was
- // worth mentioning)
- continue
- }
outreq.Header.Del(h)
}
+ // Issue 21096: tell backend applications that care about trailer support
+ // that we support trailers. (We do, but we don't go out of our way to
+ // advertise that unless the incoming client request thought it was worth
+ // mentioning.) Note that we look at req.Header, not outreq.Header, since
+ // the latter has passed through removeConnectionHeaders.
+ if httpguts.HeaderValuesContainsToken(req.Header["Te"], "trailers") {
+ outreq.Header.Set("Te", "trailers")
+ }
+
// After stripping all the hop-by-hop connection headers above, add back any
// necessary for protocol upgrades, such as for websockets.
if reqUpType != "" {
diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go
index 3acbd940e4b..3211463bcbc 100644
--- a/libgo/go/net/http/httputil/reverseproxy_test.go
+++ b/libgo/go/net/http/httputil/reverseproxy_test.go
@@ -90,8 +90,9 @@ func TestReverseProxy(t *testing.T) {
getReq, _ := http.NewRequest("GET", frontend.URL, nil)
getReq.Host = "some-name"
- getReq.Header.Set("Connection", "close")
- getReq.Header.Set("Te", "trailers")
+ getReq.Header.Set("Connection", "close, TE")
+ getReq.Header.Add("Te", "foo")
+ getReq.Header.Add("Te", "bar, trailers")
getReq.Header.Set("Proxy-Connection", "should be deleted")
getReq.Header.Set("Upgrade", "foo")
getReq.Close = true
@@ -235,6 +236,64 @@ func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) {
}
}
+func TestReverseProxyStripEmptyConnection(t *testing.T) {
+ // See Issue 46313.
+ const backendResponse = "I am the backend"
+
+ // someConnHeader is some arbitrary header to be declared as a hop-by-hop header
+ // in the Request's Connection header.
+ const someConnHeader = "X-Some-Conn-Header"
+
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if c := r.Header.Values("Connection"); len(c) != 0 {
+ t.Errorf("handler got header %q = %v; want empty", "Connection", c)
+ }
+ if c := r.Header.Get(someConnHeader); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
+ }
+ w.Header().Add("Connection", "")
+ w.Header().Add("Connection", someConnHeader)
+ w.Header().Set(someConnHeader, "should be deleted")
+ io.WriteString(w, backendResponse)
+ }))
+ defer backend.Close()
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ proxyHandler.ServeHTTP(w, r)
+ if c := r.Header.Get(someConnHeader); c != "should be deleted" {
+ t.Errorf("handler modified header %q = %q; want %q", someConnHeader, c, "should be deleted")
+ }
+ }))
+ defer frontend.Close()
+
+ getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+ getReq.Header.Add("Connection", "")
+ getReq.Header.Add("Connection", someConnHeader)
+ getReq.Header.Set(someConnHeader, "should be deleted")
+ res, err := frontend.Client().Do(getReq)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ defer res.Body.Close()
+ bodyBytes, err := io.ReadAll(res.Body)
+ if err != nil {
+ t.Fatalf("reading body: %v", err)
+ }
+ if got, want := string(bodyBytes), backendResponse; got != want {
+ t.Errorf("got body %q; want %q", got, want)
+ }
+ if c := res.Header.Get("Connection"); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", "Connection", c)
+ }
+ if c := res.Header.Get(someConnHeader); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
+ }
+}
+
func TestXForwardedFor(t *testing.T) {
const prevForwardedFor = "client ip"
const backendResponse = "I am the backend"
diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go
index cf1f5110da0..d0202c0e007 100644
--- a/libgo/go/net/http/transport_test.go
+++ b/libgo/go/net/http/transport_test.go
@@ -5318,7 +5318,6 @@ func TestMissingStatusNoPanic(t *testing.T) {
ln := newLocalListener(t)
addr := ln.Addr().String()
- shutdown := make(chan bool, 1)
done := make(chan bool)
fullAddrURL := fmt.Sprintf("http://%s", addr)
raw := "HTTP/1.1 400\r\n" +
@@ -5330,10 +5329,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
"Aloha Olaa"
go func() {
- defer func() {
- ln.Close()
- close(done)
- }()
+ defer close(done)
conn, _ := ln.Accept()
if conn != nil {
@@ -5364,7 +5360,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
t.Errorf("got=%v want=%q", err, want)
}
- close(shutdown)
+ ln.Close()
<-done
}
diff --git a/libgo/go/net/lookup.go b/libgo/go/net/lookup.go
index 5f7119872a4..0660268249b 100644
--- a/libgo/go/net/lookup.go
+++ b/libgo/go/net/lookup.go
@@ -389,8 +389,11 @@ func (r *Resolver) LookupPort(ctx context.Context, network, service string) (por
// LookupCNAME does not return an error if host does not
// contain DNS "CNAME" records, as long as host resolves to
// address records.
+//
+// The returned canonical name is validated to be a properly
+// formatted presentation-format domain name.
func LookupCNAME(host string) (cname string, err error) {
- return DefaultResolver.lookupCNAME(context.Background(), host)
+ return DefaultResolver.LookupCNAME(context.Background(), host)
}
// LookupCNAME returns the canonical name for the given host.
@@ -403,8 +406,18 @@ func LookupCNAME(host string) (cname string, err error) {
// LookupCNAME does not return an error if host does not
// contain DNS "CNAME" records, as long as host resolves to
// address records.
-func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) {
- return r.lookupCNAME(ctx, host)
+//
+// The returned canonical name is validated to be a properly
+// formatted presentation-format domain name.
+func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) {
+ cname, err := r.lookupCNAME(ctx, host)
+ if err != nil {
+ return "", err
+ }
+ if !isDomainName(cname) {
+ return "", &DNSError{Err: "CNAME target is invalid", Name: host}
+ }
+ return cname, nil
}
// LookupSRV tries to resolve an SRV query of the given service,
@@ -416,8 +429,11 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string,
// That is, it looks up _service._proto.name. To accommodate services
// publishing SRV records under non-standard names, if both service
// and proto are empty strings, LookupSRV looks up name directly.
+//
+// The returned service names are validated to be properly
+// formatted presentation-format domain names.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
- return DefaultResolver.lookupSRV(context.Background(), service, proto, name)
+ return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
}
// LookupSRV tries to resolve an SRV query of the given service,
@@ -429,28 +445,82 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
// That is, it looks up _service._proto.name. To accommodate services
// publishing SRV records under non-standard names, if both service
// and proto are empty strings, LookupSRV looks up name directly.
-func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
- return r.lookupSRV(ctx, service, proto, name)
+//
+// The returned service names are validated to be properly
+// formatted presentation-format domain names.
+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 {
+ return "", nil, err
+ }
+ if cname != "" && !isDomainName(cname) {
+ return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
+ }
+ for _, addr := range addrs {
+ if addr == nil {
+ continue
+ }
+ if !isDomainName(addr.Target) {
+ return "", nil, &DNSError{Err: "SRV target is invalid", Name: name}
+ }
+ }
+ return cname, addrs, 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.
func LookupMX(name string) ([]*MX, error) {
- return DefaultResolver.lookupMX(context.Background(), name)
+ return DefaultResolver.LookupMX(context.Background(), name)
}
// 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.
func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
- return r.lookupMX(ctx, name)
+ records, err := r.lookupMX(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ for _, mx := range records {
+ if mx == nil {
+ continue
+ }
+ if !isDomainName(mx.Host) {
+ return nil, &DNSError{Err: "MX target is invalid", Name: name}
+ }
+ }
+ return records, 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.
func LookupNS(name string) ([]*NS, error) {
- return DefaultResolver.lookupNS(context.Background(), name)
+ return DefaultResolver.LookupNS(context.Background(), name)
}
// 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.
func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
- return r.lookupNS(ctx, name)
+ records, err := r.lookupNS(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ for _, ns := range records {
+ if ns == nil {
+ continue
+ }
+ if !isDomainName(ns.Host) {
+ return nil, &DNSError{Err: "NS target is invalid", Name: name}
+ }
+ }
+ return records, nil
}
// LookupTXT returns the DNS TXT records for the given domain name.
@@ -466,14 +536,29 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error)
// LookupAddr performs a reverse lookup for the given address, returning a list
// of names mapping to that address.
//
+// The returned names are validated to be properly formatted presentation-format
+// domain names.
+//
// When using the host C library resolver, at most one result will be
// returned. To bypass the host resolver, use a custom Resolver.
func LookupAddr(addr string) (names []string, err error) {
- return DefaultResolver.lookupAddr(context.Background(), addr)
+ return DefaultResolver.LookupAddr(context.Background(), addr)
}
// LookupAddr performs a reverse lookup for the given address, returning a list
// of names mapping to that address.
-func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) {
- return r.lookupAddr(ctx, addr)
+//
+// The returned names are validated to be properly formatted presentation-format
+// domain names.
+func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
+ names, err := r.lookupAddr(ctx, addr)
+ if err != nil {
+ return nil, err
+ }
+ for _, name := range names {
+ if !isDomainName(name) {
+ return nil, &DNSError{Err: "PTR target is invalid", Name: addr}
+ }
+ }
+ return names, nil
}
diff --git a/libgo/go/os/signal/signal_test.go b/libgo/go/os/signal/signal_test.go
index db947568dca..1f89780c455 100644
--- a/libgo/go/os/signal/signal_test.go
+++ b/libgo/go/os/signal/signal_test.go
@@ -15,6 +15,7 @@ import (
"os"
"os/exec"
"runtime"
+ "runtime/trace"
"strconv"
"sync"
"syscall"
@@ -853,3 +854,44 @@ func TestNotifyContextStringer(t *testing.T) {
t.Errorf("c.String() = %q, want %q", got, want)
}
}
+
+// #44193 test signal handling while stopping and starting the world.
+func TestSignalTrace(t *testing.T) {
+ done := make(chan struct{})
+ quit := make(chan struct{})
+ c := make(chan os.Signal, 1)
+ Notify(c, syscall.SIGHUP)
+
+ // Source and sink for signals busy loop unsynchronized with
+ // trace starts and stops. We are ultimately validating that
+ // signals and runtime.(stop|start)TheWorldGC are compatible.
+ go func() {
+ defer close(done)
+ defer Stop(c)
+ pid := syscall.Getpid()
+ for {
+ select {
+ case <-quit:
+ return
+ default:
+ syscall.Kill(pid, syscall.SIGHUP)
+ }
+ waitSig(t, c, syscall.SIGHUP)
+ }
+ }()
+
+ for i := 0; i < 100; i++ {
+ buf := new(bytes.Buffer)
+ if err := trace.Start(buf); err != nil {
+ t.Fatalf("[%d] failed to start tracing: %v", i, err)
+ }
+ time.After(1 * time.Microsecond)
+ trace.Stop()
+ size := buf.Len()
+ if size == 0 {
+ t.Fatalf("[%d] trace is empty", i)
+ }
+ }
+ close(quit)
+ <-done
+}
diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go
index 42411e9179a..73d7aaaf9f8 100644
--- a/libgo/go/runtime/pprof/pprof_test.go
+++ b/libgo/go/runtime/pprof/pprof_test.go
@@ -279,7 +279,8 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri
broken := false
switch runtime.GOOS {
- case "darwin", "ios", "dragonfly", "netbsd", "illumos", "solaris":
+ // See https://golang.org/issue/45170 for AIX.
+ case "darwin", "ios", "dragonfly", "netbsd", "illumos", "solaris", "aix":
broken = true
case "openbsd":
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index eec44db1919..037e7798a38 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -1287,6 +1287,9 @@ func mPark() {
g := getg()
for {
notesleep(&g.m.park)
+ // Note, because of signal handling by this parked m,
+ // a preemptive mDoFixup() may actually occur via
+ // mDoFixupAndOSYield(). (See golang.org/issue/44193)
noteclear(&g.m.park)
if !mDoFixup() {
return
@@ -1949,9 +1952,21 @@ var mFixupRace struct {
// mDoFixup runs any outstanding fixup function for the running m.
// Returns true if a fixup was outstanding and actually executed.
//
+// Note: to avoid deadlocks, and the need for the fixup function
+// itself to be async safe, signals are blocked for the working m
+// while it holds the mFixup lock. (See golang.org/issue/44193)
+//
//go:nosplit
func mDoFixup() bool {
_g_ := getg()
+ if used := atomic.Load(&_g_.m.mFixup.used); used == 0 {
+ return false
+ }
+
+ // slow path - if fixup fn is used, block signals and lock.
+ var sigmask sigset
+ sigsave(&sigmask)
+ sigblock(false)
lock(&_g_.m.mFixup.lock)
fn := _g_.m.mFixup.fn
if fn != nil {
@@ -1972,9 +1987,20 @@ func mDoFixup() bool {
fn(false)
}
unlock(&_g_.m.mFixup.lock)
+ msigrestore(sigmask)
return fn != nil
}
+// mDoFixupAndOSYield is called when an m is unable to send a signal
+// because the allThreadsSyscall mechanism is in progress. That is, an
+// mPark() has been interrupted with this signal handler so we need to
+// ensure the fixup is executed from this context.
+//go:nosplit
+func mDoFixupAndOSYield() {
+ mDoFixup()
+ osyield()
+}
+
// templateThread is a thread in a known-good state that exists solely
// to start new threads in known-good states when the calling thread
// may not be in a good state.
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
index 4b13cfc0123..1879b829be7 100644
--- a/libgo/go/runtime/runtime2.go
+++ b/libgo/go/runtime/runtime2.go
@@ -584,10 +584,13 @@ type m struct {
syscalltick uint32
freelink *m // on sched.freem
- // mFixup is used to synchronize OS related m state (credentials etc)
- // use mutex to access.
+ // mFixup is used to synchronize OS related m state
+ // (credentials etc) use mutex to access. To avoid deadlocks
+ // an atomic.Load() of used being zero in mDoFixupFn()
+ // guarantees fn is nil.
mFixup struct {
lock mutex
+ used uint32
fn func(bool) bool
}
diff --git a/libgo/go/runtime/sigqueue.go b/libgo/go/runtime/sigqueue.go
index ca41b0552d5..7ca755740d2 100644
--- a/libgo/go/runtime/sigqueue.go
+++ b/libgo/go/runtime/sigqueue.go
@@ -119,7 +119,7 @@ Send:
}
case sigFixup:
// nothing to do - we need to wait for sigIdle.
- osyield()
+ mDoFixupAndOSYield()
}
}
diff --git a/libgo/go/time/zoneinfo.go b/libgo/go/time/zoneinfo.go
index 6db94434747..57052338d0a 100644
--- a/libgo/go/time/zoneinfo.go
+++ b/libgo/go/time/zoneinfo.go
@@ -178,7 +178,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64)
// If we're at the end of the known zone transitions,
// try the extend string.
if lo == len(tx)-1 && l.extend != "" {
- if ename, eoffset, estart, eend, ok := tzset(l.extend, end, sec); ok {
+ if ename, eoffset, estart, eend, _, ok := tzset(l.extend, end, sec); ok {
return ename, eoffset, estart, eend
}
}
@@ -244,7 +244,7 @@ func (l *Location) firstZoneUsed() bool {
// We call this a tzset string since in C the function tzset reads TZ.
// The return values are as for lookup, plus ok which reports whether the
// parse succeeded.
-func tzset(s string, initEnd, sec int64) (name string, offset int, start, end int64, ok bool) {
+func tzset(s string, initEnd, sec int64) (name string, offset int, start, end int64, isDST, ok bool) {
var (
stdName, dstName string
stdOffset, dstOffset int
@@ -255,7 +255,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
stdOffset, s, ok = tzsetOffset(s)
}
if !ok {
- return "", 0, 0, 0, false
+ return "", 0, 0, 0, false, false
}
// The numbers in the tzset string are added to local time to get UTC,
@@ -265,7 +265,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
if len(s) == 0 || s[0] == ',' {
// No daylight savings time.
- return stdName, stdOffset, initEnd, omega, true
+ return stdName, stdOffset, initEnd, omega, false, true
}
dstName, s, ok = tzsetName(s)
@@ -278,7 +278,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
}
}
if !ok {
- return "", 0, 0, 0, false
+ return "", 0, 0, 0, false, false
}
if len(s) == 0 {
@@ -287,19 +287,19 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
}
// The TZ definition does not mention ';' here but tzcode accepts it.
if s[0] != ',' && s[0] != ';' {
- return "", 0, 0, 0, false
+ return "", 0, 0, 0, false, false
}
s = s[1:]
var startRule, endRule rule
startRule, s, ok = tzsetRule(s)
if !ok || len(s) == 0 || s[0] != ',' {
- return "", 0, 0, 0, false
+ return "", 0, 0, 0, false, false
}
s = s[1:]
endRule, s, ok = tzsetRule(s)
if !ok || len(s) > 0 {
- return "", 0, 0, 0, false
+ return "", 0, 0, 0, false, false
}
year, _, _, yday := absDate(uint64(sec+unixToInternal+internalToAbsolute), false)
@@ -313,10 +313,15 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
startSec := int64(tzruleTime(year, startRule, stdOffset))
endSec := int64(tzruleTime(year, endRule, dstOffset))
+ dstIsDST, stdIsDST := true, false
+ // Note: this is a flipping of "DST" and "STD" while retaining the labels
+ // This happens in southern hemispheres. The labelling here thus is a little
+ // inconsistent with the goal.
if endSec < startSec {
startSec, endSec = endSec, startSec
stdName, dstName = dstName, stdName
stdOffset, dstOffset = dstOffset, stdOffset
+ stdIsDST, dstIsDST = dstIsDST, stdIsDST
}
// The start and end values that we return are accurate
@@ -324,11 +329,11 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
// just the start and end of the year. That suffices for
// the only caller that cares, which is Date.
if ysec < startSec {
- return stdName, stdOffset, abs, startSec + abs, true
+ return stdName, stdOffset, abs, startSec + abs, stdIsDST, true
} else if ysec >= endSec {
- return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, true
+ return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, stdIsDST, true
} else {
- return dstName, dstOffset, startSec + abs, endSec + abs, true
+ return dstName, dstOffset, startSec + abs, endSec + abs, dstIsDST, true
}
}
diff --git a/libgo/go/time/zoneinfo_read.go b/libgo/go/time/zoneinfo_read.go
index 463e420de41..c8c725697b0 100644
--- a/libgo/go/time/zoneinfo_read.go
+++ b/libgo/go/time/zoneinfo_read.go
@@ -249,8 +249,8 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
// This also avoids a panic later when we add and then use a fake transition (golang.org/issue/29437).
return nil, badData
}
- zone := make([]zone, nzone)
- for i := range zone {
+ zones := make([]zone, nzone)
+ for i := range zones {
var ok bool
var n uint32
if n, ok = zonedata.big4(); !ok {
@@ -259,22 +259,22 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
if uint32(int(n)) != n {
return nil, badData
}
- zone[i].offset = int(int32(n))
+ zones[i].offset = int(int32(n))
var b byte
if b, ok = zonedata.byte(); !ok {
return nil, badData
}
- zone[i].isDST = b != 0
+ zones[i].isDST = b != 0
if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) {
return nil, badData
}
- zone[i].name = byteString(abbrev[b:])
+ zones[i].name = byteString(abbrev[b:])
if runtime.GOOS == "aix" && len(name) > 8 && (name[:8] == "Etc/GMT+" || name[:8] == "Etc/GMT-") {
// There is a bug with AIX 7.2 TL 0 with files in Etc,
// GMT+1 will return GMT-1 instead of GMT+1 or -01.
if name != "Etc/GMT+0" {
// GMT+0 is OK
- zone[i].name = name[4:]
+ zones[i].name = name[4:]
}
}
}
@@ -297,7 +297,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
}
}
tx[i].when = n
- if int(txzones[i]) >= len(zone) {
+ if int(txzones[i]) >= len(zones) {
return nil, badData
}
tx[i].index = txzones[i]
@@ -316,7 +316,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
}
// Committed to succeed.
- l := &Location{zone: zone, tx: tx, name: name, extend: extend}
+ l := &Location{zone: zones, tx: tx, name: name, extend: extend}
// Fill in the cache with information about right now,
// since that will be the most common lookup.
@@ -325,26 +325,27 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
l.cacheStart = tx[i].when
l.cacheEnd = omega
- zoneIdx := tx[i].index
+ l.cacheZone = &l.zone[tx[i].index]
if i+1 < len(tx) {
l.cacheEnd = tx[i+1].when
} else if l.extend != "" {
// If we're at the end of the known zone transitions,
// try the extend string.
- if name, _, estart, eend, ok := tzset(l.extend, l.cacheEnd, sec); ok {
+ if name, offset, estart, eend, isDST, ok := tzset(l.extend, l.cacheEnd, sec); ok {
l.cacheStart = estart
l.cacheEnd = eend
- // Find the zone that is returned by tzset,
- // the last transition is not always the correct zone.
- for i, z := range l.zone {
- if z.name == name {
- zoneIdx = uint8(i)
- break
+ // Find the zone that is returned by tzset to avoid allocation if possible.
+ if zoneIdx := findZone(l.zone, name, offset, isDST); zoneIdx != -1 {
+ l.cacheZone = &l.zone[zoneIdx]
+ } else {
+ l.cacheZone = &zone{
+ name: name,
+ offset: offset,
+ isDST: isDST,
}
}
}
}
- l.cacheZone = &l.zone[zoneIdx]
break
}
}
@@ -352,6 +353,15 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
return l, nil
}
+func findZone(zones []zone, name string, offset int, isDST bool) int {
+ for i, z := range zones {
+ if z.name == name && z.offset == offset && z.isDST == isDST {
+ return i
+ }
+ }
+ return -1
+}
+
// loadTzinfoFromDirOrZip returns the contents of the file with the given name
// in dir. dir can either be an uncompressed zip file, or a directory.
func loadTzinfoFromDirOrZip(dir, name string) ([]byte, error) {
diff --git a/libgo/go/time/zoneinfo_test.go b/libgo/go/time/zoneinfo_test.go
index 3e32da02b2e..a9b4f077856 100644
--- a/libgo/go/time/zoneinfo_test.go
+++ b/libgo/go/time/zoneinfo_test.go
@@ -192,6 +192,7 @@ func TestMalformedTZData(t *testing.T) {
var slimTests = []struct {
zoneName string
tzData string
+ date func(*time.Location) time.Time
wantName string
wantOffset int
}{
@@ -199,6 +200,7 @@ var slimTests = []struct {
// 2020b slim tzdata for Europe/Berlin.
zoneName: "Europe/Berlin",
tzData: "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\f\x88\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\rLMT\x00CEST\x00CET\x00CEMT\x00\nCET-1CEST,M3.5.0,M10.5.0/3\n",
+ date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
wantName: "CET",
wantOffset: 3600,
},
@@ -206,6 +208,7 @@ var slimTests = []struct {
// 2021a slim tzdata for America/Nuuk.
zoneName: "America/Nuuk",
tzData: "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80h\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xffπ\x00\x00\xff\xff\xd5\xd0\x00\x04\xff\xff\xe3\xe0\x01\bLMT\x00-03\x00-02\x00\n<-03>3<-02>,M3.5.0/-2,M10.5.0/-1\n",
+ date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
wantName: "-03",
wantOffset: -10800,
},
@@ -213,9 +216,18 @@ var slimTests = []struct {
// 2021a slim tzdata for Asia/Gaza.
zoneName: "Asia/Gaza",
tzData: "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\xb0\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xad.\x9c\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 P\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11LMT\x00EEST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.4.4/49\n",
+ date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
wantName: "EET",
wantOffset: 7200,
},
+ {
+ // 2021a slim tzdata for Europe/Dublin.
+ zoneName: "Europe/Dublin",
+ tzData: "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\x08\x00\x00\x00\x14\xff\xff\xff\xffW\xd1\n\xdc\xff\xff\xff\xff\x9b&\xb3\x91\xff\xff\xff\xff\x9b\xd6\x0b\x11\xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4\xc3\xa0\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba\x20\xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c\x20\xff\xff\xff\xff\xa3{\xc8\xa0\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb\x20\xff\xff\xff\xff\xa6%`\x20\xff\xff\xff\xff\xa7'\xc6\x20\xff\xff\xff\xff\xa8*,\x20\xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00\xd3\xa0\xff\xff\xff\xff\xaa\xd5\x15\x20\xff\xff\xff\xff\xab\xe9\xf0\x20\xff\xff\xff\xff\xac\xc7l\x20\xff\xff\xff\xff\xad\xc9\xd2\x20\xff\xff\xff\xff\xae\xa7N\x20\xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870\x20\xff\xff\xff\xff\xb1\x92\xd0\xa0\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ\x20\xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xef\xd4\xa0\xff\xff\xff\xff\xba\xe9\x00\x20\xff\xff\xff\xff\xbb\xd8\xf1\x20\xff\xff\xff\xff\xbc\xdbW\x20\xff\xff\xff\xff\xbd\xb8\xd3\x20\xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5\x20\xff\xff\xff\xff\xc0\x9b\x1b\x20\xff\xff\xff\xff\xc1x\x97\x20\xff\xff\xff\xff\xc2z\xfd\x20\xff\xff\xff\xff\xc3Xy\x20\xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[\x20\xff\xff\xff\xff\xc6:\xc1\x20\xff\xff\xff\xff\xc7X\xd6\xa0\xff\xff\xff\xff\xc7\xda\x09\xa0\xff\xff\xff\xff\xd4I\xe0\x20\xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd6N\xac\x20\xff\xff\xff\xff\xd7,(\x20\xff\xff\xff\xff\xd8.\x8e\x20\xff\xff\xff\xff\xd8\xf9\x95\x20\xff\xff\xff\xff\xda\x0ep\x20\xff\xff\xff\xff\xda\xeb\xec\x20\xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce\x20\xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\xde\xb4\xea\xa0\xff\xff\xff\xff\xdf\xae\x16\x20\xff\xff\xff\xff\xe0\x94\xcc\xa0\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt\x20\xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\x0c\xa0\xff\xff\xff\xff\xe6=\xad\x20\xff\xff\xff\xff\xe7\x1b)\x20\xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\x0b\x20\xff\xff\xff\xff\xe9\xfdq\x20\xff\xff\xff\xff\xea\xda\xed\x20\xff\xff\xff\xff\xeb\xddS\x20\xff\xff\xff\xff\xec\xba\xcf\x20\xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\xee\x9a\xb1\x20\xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f}\x20\xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\x7f_\x20\xff\xff\xff\xff\xf3Jf\x20\xff\xff\xff\xff\xf4_A\x20\xff\xff\xff\xff\xf5!\x0d\xa0\xff\xff\xff\xff\xf6?#\x20\xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05\x20\xff\xff\xff\xff\xf8\xe0\xd1\xa0\xff\xff\xff\xff\xf9\xfe\xe7\x20\xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfd\xc7\xbbp\x00\x00\x00\x00\x03p\xc6\x20\x00\x00\x00\x00\x04)X\x20\x00\x00\x00\x00\x05P\xa8\x20\x00\x00\x00\x00\x06\x09:\x20\x00\x00\x00\x00\x070\x8a\x20\x00\x00\x00\x00\x07\xe9\x1c\x20\x00\x00\x00\x00\x09\x10l\x20\x00\x00\x00\x00\x09\xc8\xfe\x20\x00\x00\x00\x00\n\xf0N\x20\x00\x00\x00\x00\x0b\xb2\x1a\xa0\x00\x00\x00\x00\x0c\xd00\x20\x00\x00\x00\x00\x0d\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12\x20\x00\x00\x00\x00\x0fq\xde\xa0\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168\xc6\x90\x00\x00\x00\x00\x17\x03\xcd\x90\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18\xe3\xaf\x90\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1a\xc3\x91\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00\x20lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\x22LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\x0c\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9\xd3\x90\x00\x00\x00\x00-\x94\xda\x90\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\xff\xff\xfa$\x00\x00\xff\xff\xfa\x0f\x00\x04\x00\x00\x08\x1f\x01\x08\x00\x00\x0e\x10\x01\x0c\x00\x00\x00\x00\x00\x10\x00\x00\x0e\x10\x01\x08\x00\x00\x00\x00\x01\x10\x00\x00\x0e\x10\x00\x08LMT\x00DMT\x00IST\x00BST\x00GMT\x00\nIST-1GMT0,M10.5.0,M3.5.0/1\n",
+ date: func(loc *time.Location) time.Time { return time.Date(2021, time.April, 2, 11, 12, 13, 0, loc) },
+ wantName: "IST",
+ wantOffset: 3600,
+ },
}
func TestLoadLocationFromTZDataSlim(t *testing.T) {
@@ -225,7 +237,7 @@ func TestLoadLocationFromTZDataSlim(t *testing.T) {
t.Fatal(err)
}
- d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference)
+ d := test.date(reference)
tzName, tzOffset := d.Zone()
if tzName != test.wantName {
t.Errorf("Zone name == %s, want %s", tzName, test.wantName)
@@ -245,20 +257,21 @@ func TestTzset(t *testing.T) {
off int
start int64
end int64
+ isDST bool
ok bool
}{
- {"", 0, 0, "", 0, 0, 0, false},
- {"PST8PDT,M3.2.0,M11.1.0", 0, 2159200800, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true},
- {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173599, "PST", -8 * 60 * 60, 2145916800, 2152173600, true},
- {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173600, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true},
- {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173601, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true},
- {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733199, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true},
- {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733200, "PST", -8 * 60 * 60, 2172733200, 2177452800, true},
- {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733201, "PST", -8 * 60 * 60, 2172733200, 2177452800, true},
+ {"", 0, 0, "", 0, 0, 0, false, false},
+ {"PST8PDT,M3.2.0,M11.1.0", 0, 2159200800, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
+ {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173599, "PST", -8 * 60 * 60, 2145916800, 2152173600, false, true},
+ {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173600, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
+ {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173601, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
+ {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733199, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true},
+ {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733200, "PST", -8 * 60 * 60, 2172733200, 2177452800, false, true},
+ {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733201, "PST", -8 * 60 * 60, 2172733200, 2177452800, false, true},
} {
- name, off, start, end, ok := time.Tzset(test.inStr, test.inEnd, test.inSec)
- if name != test.name || off != test.off || start != test.start || end != test.end || ok != test.ok {
- t.Errorf("tzset(%q, %d, %d) = %q, %d, %d, %d, %t, want %q, %d, %d, %d, %t", test.inStr, test.inEnd, test.inSec, name, off, start, end, ok, test.name, test.off, test.start, test.end, test.ok)
+ name, off, start, end, isDST, ok := time.Tzset(test.inStr, test.inEnd, test.inSec)
+ if name != test.name || off != test.off || start != test.start || end != test.end || isDST != test.isDST || ok != test.ok {
+ t.Errorf("tzset(%q, %d, %d) = %q, %d, %d, %d, %t, %t, want %q, %d, %d, %d, %t, %t", test.inStr, test.inEnd, test.inSec, name, off, start, end, isDST, ok, test.name, test.off, test.start, test.end, test.isDST, test.ok)
}
}
}
diff --git a/libgo/go/vendor/modules.txt b/libgo/go/vendor/modules.txt
index 04bb67e58d6..b18d36639a1 100644
--- a/libgo/go/vendor/modules.txt
+++ b/libgo/go/vendor/modules.txt
@@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519
golang.org/x/crypto/hkdf
golang.org/x/crypto/internal/subtle
golang.org/x/crypto/poly1305
-# golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
+# golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b
## explicit
golang.org/x/net/dns/dnsmessage
golang.org/x/net/http/httpguts