libgo: update to Go1.16.5 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/326772
This commit is contained in:
parent
00d07ec6e1
commit
ee52bf609b
|
@ -1,4 +1,4 @@
|
||||||
5a801b15699cced5203af5c7339b375cd55ecbac
|
bcafcb3c39530bb325514d6377747eb3127d1a03
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the last
|
The first line of this file holds the git revision number of the last
|
||||||
merge done from the gofrontend repository.
|
merge done from the gofrontend repository.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
9baddd3f21230c55f0ad2a10f5f20579dcf0a0bb
|
7677616a263e8ded606cc8297cb67ddc667a876e
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the
|
The first line of this file holds the git revision number of the
|
||||||
last merge done from the master library sources.
|
last merge done from the master library sources.
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
go1.16.3
|
go1.16.5
|
||||||
|
|
|
@ -99,7 +99,15 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
z.r = r
|
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
|
z.Comment = end.comment
|
||||||
rs := io.NewSectionReader(r, 0, size)
|
rs := io.NewSectionReader(r, 0, size)
|
||||||
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
|
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.
|
// 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 {
|
type fileListEntry struct {
|
||||||
name string
|
name string
|
||||||
file *File // nil for directories
|
file *File
|
||||||
|
isDir bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileInfoDirEntry interface {
|
type fileInfoDirEntry interface {
|
||||||
|
@ -640,20 +649,26 @@ type fileInfoDirEntry interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *fileListEntry) stat() fileInfoDirEntry {
|
func (e *fileListEntry) stat() fileInfoDirEntry {
|
||||||
if e.file != nil {
|
if !e.isDir {
|
||||||
return headerFileInfo{&e.file.FileHeader}
|
return headerFileInfo{&e.file.FileHeader}
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used for directories.
|
// Only used for directories.
|
||||||
func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
|
func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
|
||||||
func (f *fileListEntry) Size() int64 { return 0 }
|
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) Mode() fs.FileMode { return fs.ModeDir | 0555 }
|
func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
|
||||||
func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
|
func (f *fileListEntry) IsDir() bool { return true }
|
||||||
func (f *fileListEntry) IsDir() bool { return true }
|
func (f *fileListEntry) Sys() interface{} { return nil }
|
||||||
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 }
|
func (f *fileListEntry) Info() (fs.FileInfo, error) { return f, nil }
|
||||||
|
|
||||||
|
@ -673,15 +688,32 @@ func toValidName(name string) string {
|
||||||
func (r *Reader) initFileList() {
|
func (r *Reader) initFileList() {
|
||||||
r.fileListOnce.Do(func() {
|
r.fileListOnce.Do(func() {
|
||||||
dirs := make(map[string]bool)
|
dirs := make(map[string]bool)
|
||||||
|
knownDirs := make(map[string]bool)
|
||||||
for _, file := range r.File {
|
for _, file := range r.File {
|
||||||
|
isDir := len(file.Name) > 0 && file.Name[len(file.Name)-1] == '/'
|
||||||
name := toValidName(file.Name)
|
name := toValidName(file.Name)
|
||||||
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
|
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
|
||||||
dirs[dir] = true
|
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 {
|
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) })
|
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) {
|
if e == nil || !fs.ValidPath(name) {
|
||||||
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
|
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
|
return &openDir{e, r.openReadDir(name), 0}, nil
|
||||||
}
|
}
|
||||||
rc, err := e.file.Open()
|
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
|
return name[:i], name[i+1:], isDir
|
||||||
}
|
}
|
||||||
|
|
||||||
var dotFile = &fileListEntry{name: "./"}
|
var dotFile = &fileListEntry{name: "./", isDir: true}
|
||||||
|
|
||||||
func (r *Reader) openLookup(name string) *fileListEntry {
|
func (r *Reader) openLookup(name string) *fileListEntry {
|
||||||
if name == "." {
|
if name == "." {
|
||||||
|
|
|
@ -1073,12 +1073,62 @@ func TestIssue12449(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFS(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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := fstest.TestFS(z, "hello", "dir/bar", "dir/empty", "readonly"); err != nil {
|
defer z.Close()
|
||||||
t.Fatal(err)
|
|
||||||
|
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)
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
|
@ -86,9 +86,11 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
if !modload.HasModRoot() && len(args) == 0 {
|
if !modload.HasModRoot() && len(args) == 0 {
|
||||||
base.Fatalf("go mod download: no modules specified (see 'go help mod download')")
|
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"}
|
args = []string{"all"}
|
||||||
} else if modload.HasModRoot() {
|
}
|
||||||
|
if modload.HasModRoot() {
|
||||||
modload.LoadModFile(ctx) // to fill Target
|
modload.LoadModFile(ctx) // to fill Target
|
||||||
targetAtUpgrade := modload.Target.Path + "@upgrade"
|
targetAtUpgrade := modload.Target.Path + "@upgrade"
|
||||||
targetAtPatch := modload.Target.Path + "@patch"
|
targetAtPatch := modload.Target.Path + "@patch"
|
||||||
|
@ -137,7 +139,20 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
listRetractions := false
|
listRetractions := false
|
||||||
type token struct{}
|
type token struct{}
|
||||||
sem := make(chan token, runtime.GOMAXPROCS(0))
|
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 {
|
if info.Replace != nil {
|
||||||
info = info.Replace
|
info = info.Replace
|
||||||
}
|
}
|
||||||
|
@ -187,6 +202,13 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
base.ExitIfErrors()
|
base.ExitIfErrors()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update go.mod and especially go.sum if needed.
|
// If there were explicit arguments, update go.mod and especially go.sum.
|
||||||
modload.WriteGoMod()
|
// '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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
modload.ForceUseModules = true
|
modload.ForceUseModules = true
|
||||||
modload.RootMode = modload.NeedRoot
|
modload.RootMode = modload.NeedRoot
|
||||||
|
|
||||||
|
modload.CheckTidyVersion(ctx, tidyE)
|
||||||
|
|
||||||
modload.LoadPackages(ctx, modload.PackageOpts{
|
modload.LoadPackages(ctx, modload.PackageOpts{
|
||||||
Tags: imports.AnyTags(),
|
Tags: imports.AnyTags(),
|
||||||
ResolveMissingImports: true,
|
ResolveMissingImports: true,
|
||||||
|
|
|
@ -11,10 +11,13 @@ import (
|
||||||
"cmd/go/internal/mvs"
|
"cmd/go/internal/mvs"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/build"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/mod/modfile"
|
||||||
"golang.org/x/mod/module"
|
"golang.org/x/mod/module"
|
||||||
|
"golang.org/x/mod/semver"
|
||||||
)
|
)
|
||||||
|
|
||||||
// buildList is the list of modules to use for building packages.
|
// buildList is the list of modules to use for building packages.
|
||||||
|
@ -226,6 +229,33 @@ func ReloadBuildList() []module.Version {
|
||||||
return capVersionSlice(buildList)
|
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
|
// TidyBuildList trims the build list to the minimal requirements needed to
|
||||||
// retain the same versions of all packages from the preceding call to
|
// retain the same versions of all packages from the preceding call to
|
||||||
// LoadPackages.
|
// LoadPackages.
|
||||||
|
|
|
@ -5,7 +5,7 @@ module "rsc.io/sampler"
|
||||||
|
|
||||||
require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c
|
require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c
|
||||||
-- .info --
|
-- .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 --
|
-- hello.go --
|
||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
|
|
@ -107,13 +107,28 @@ stderr '^go mod download: skipping argument m that resolves to the main module\n
|
||||||
! go mod download m@latest
|
! go mod download m@latest
|
||||||
stderr '^go mod download: m@latest: malformed module path "m": missing dot in first path element$'
|
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
|
cd update
|
||||||
|
cp go.mod.orig go.mod
|
||||||
! exists go.sum
|
! exists go.sum
|
||||||
go mod download
|
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
|
grep '^rsc.io/sampler v1.3.0 ' go.sum
|
||||||
go list -m rsc.io/sampler
|
cp go.mod.orig go.mod
|
||||||
stdout '^rsc.io/sampler v1.3.0$'
|
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
|
# allow go mod download without go.mod
|
||||||
env GO111MODULE=auto
|
env GO111MODULE=auto
|
||||||
|
@ -131,7 +146,7 @@ stderr 'get '$GOPROXY
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
-- update/go.mod --
|
-- update/go.mod.orig --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
go 1.16
|
go 1.16
|
||||||
|
@ -140,3 +155,16 @@ require (
|
||||||
rsc.io/quote v1.5.2
|
rsc.io/quote v1.5.2
|
||||||
rsc.io/sampler v1.2.1 // older version than in build list
|
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=
|
||||||
|
|
|
@ -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
|
# 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
|
# 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
|
# ".go/" should try to list a package regardless of whether a file exists at the
|
||||||
|
@ -31,3 +28,10 @@ module m
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require example.com/dotgo.go v1.0.0
|
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"
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
|
|
||||||
# Populate go.sum.
|
|
||||||
# TODO(golang.org/issue/41297): we shouldn't need go.sum. None of the commands
|
# TODO(golang.org/issue/41297): we shouldn't need go.sum. None of the commands
|
||||||
# below depend on the build list.
|
# below depend on the build list.
|
||||||
go mod download
|
|
||||||
|
|
||||||
go list -m -versions rsc.io/quote
|
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$'
|
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
|
module x
|
||||||
require rsc.io/quote v1.0.0
|
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 --
|
-- use.go --
|
||||||
package use
|
package use
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ stderr '^no required module provides package rsc.io/quote; to add it:\n\tgo get
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
go 1.20
|
go 1.16
|
||||||
|
|
||||||
-- x.go --
|
-- x.go --
|
||||||
package x
|
package x
|
||||||
|
@ -104,7 +104,7 @@ require (
|
||||||
-- go.mod.redundant --
|
-- go.mod.redundant --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
go 1.20
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
rsc.io/quote v1.5.2
|
rsc.io/quote v1.5.2
|
||||||
|
@ -114,7 +114,7 @@ require (
|
||||||
-- go.mod.indirect --
|
-- go.mod.indirect --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
go 1.20
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
rsc.io/quote v1.5.2 // indirect
|
rsc.io/quote v1.5.2 // indirect
|
||||||
|
@ -124,7 +124,7 @@ require (
|
||||||
-- go.mod.untidy --
|
-- go.mod.untidy --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
go 1.20
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
rsc.io/sampler v1.3.0 // indirect
|
rsc.io/sampler v1.3.0 // indirect
|
||||||
|
|
|
@ -4,7 +4,7 @@ go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
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/sys v0.0.0-20201204225414-ed752295db88 // indirect
|
||||||
golang.org/x/text v0.3.4 // indirect
|
golang.org/x/text v0.3.4 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
@ -137,11 +137,13 @@ func trimOWS(x string) string {
|
||||||
// contains token amongst its comma-separated tokens, ASCII
|
// contains token amongst its comma-separated tokens, ASCII
|
||||||
// case-insensitively.
|
// case-insensitively.
|
||||||
func headerValueContainsToken(v string, token string) bool {
|
func headerValueContainsToken(v string, token string) bool {
|
||||||
v = trimOWS(v)
|
for comma := strings.IndexByte(v, ','); comma != -1; comma = strings.IndexByte(v, ',') {
|
||||||
if comma := strings.IndexByte(v, ','); comma != -1 {
|
if tokenEqual(trimOWS(v[:comma]), token) {
|
||||||
return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
|
return true
|
||||||
|
}
|
||||||
|
v = v[comma+1:]
|
||||||
}
|
}
|
||||||
return tokenEqual(v, token)
|
return tokenEqual(trimOWS(v), token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// lowerASCII returns the ASCII lowercase version of b.
|
// lowerASCII returns the ASCII lowercase version of b.
|
||||||
|
|
|
@ -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)
|
// 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
|
// exponent may be provided as well, except for hexadecimal floats which
|
||||||
// only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot
|
// 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
|
// 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.
|
// operation failed, the value of z is undefined but the returned value is nil.
|
||||||
func (z *Rat) SetString(s string) (*Rat, bool) {
|
func (z *Rat) SetString(s string) (*Rat, bool) {
|
||||||
|
@ -169,6 +170,9 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
n = -n
|
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
|
pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
|
||||||
if exp5 > 0 {
|
if exp5 > 0 {
|
||||||
z.a.abs = z.a.abs.mul(z.a.abs, pow5)
|
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
|
// apply exp2 contributions
|
||||||
|
if exp2 < -1e7 || exp2 > 1e7 {
|
||||||
|
return nil, false // avoid excessively large exponents
|
||||||
|
}
|
||||||
if exp2 > 0 {
|
if exp2 > 0 {
|
||||||
if int64(uint(exp2)) != exp2 {
|
|
||||||
panic("exponent too large")
|
|
||||||
}
|
|
||||||
z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
|
z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
|
||||||
} else if exp2 < 0 {
|
} 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))
|
z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1798,3 +1798,161 @@ func TestPTRandNonPTR(t *testing.T) {
|
||||||
t.Errorf("names = %q; want %q", names, want)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -248,22 +248,18 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
// important is "Connection" because we want a persistent
|
// important is "Connection" because we want a persistent
|
||||||
// connection, regardless of what the client sent to us.
|
// connection, regardless of what the client sent to us.
|
||||||
for _, h := range hopHeaders {
|
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)
|
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
|
// After stripping all the hop-by-hop connection headers above, add back any
|
||||||
// necessary for protocol upgrades, such as for websockets.
|
// necessary for protocol upgrades, such as for websockets.
|
||||||
if reqUpType != "" {
|
if reqUpType != "" {
|
||||||
|
|
|
@ -90,8 +90,9 @@ func TestReverseProxy(t *testing.T) {
|
||||||
|
|
||||||
getReq, _ := http.NewRequest("GET", frontend.URL, nil)
|
getReq, _ := http.NewRequest("GET", frontend.URL, nil)
|
||||||
getReq.Host = "some-name"
|
getReq.Host = "some-name"
|
||||||
getReq.Header.Set("Connection", "close")
|
getReq.Header.Set("Connection", "close, TE")
|
||||||
getReq.Header.Set("Te", "trailers")
|
getReq.Header.Add("Te", "foo")
|
||||||
|
getReq.Header.Add("Te", "bar, trailers")
|
||||||
getReq.Header.Set("Proxy-Connection", "should be deleted")
|
getReq.Header.Set("Proxy-Connection", "should be deleted")
|
||||||
getReq.Header.Set("Upgrade", "foo")
|
getReq.Header.Set("Upgrade", "foo")
|
||||||
getReq.Close = true
|
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) {
|
func TestXForwardedFor(t *testing.T) {
|
||||||
const prevForwardedFor = "client ip"
|
const prevForwardedFor = "client ip"
|
||||||
const backendResponse = "I am the backend"
|
const backendResponse = "I am the backend"
|
||||||
|
|
|
@ -5318,7 +5318,6 @@ func TestMissingStatusNoPanic(t *testing.T) {
|
||||||
|
|
||||||
ln := newLocalListener(t)
|
ln := newLocalListener(t)
|
||||||
addr := ln.Addr().String()
|
addr := ln.Addr().String()
|
||||||
shutdown := make(chan bool, 1)
|
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
fullAddrURL := fmt.Sprintf("http://%s", addr)
|
fullAddrURL := fmt.Sprintf("http://%s", addr)
|
||||||
raw := "HTTP/1.1 400\r\n" +
|
raw := "HTTP/1.1 400\r\n" +
|
||||||
|
@ -5330,10 +5329,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
|
||||||
"Aloha Olaa"
|
"Aloha Olaa"
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer close(done)
|
||||||
ln.Close()
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
|
|
||||||
conn, _ := ln.Accept()
|
conn, _ := ln.Accept()
|
||||||
if conn != nil {
|
if conn != nil {
|
||||||
|
@ -5364,7 +5360,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
|
||||||
t.Errorf("got=%v want=%q", err, want)
|
t.Errorf("got=%v want=%q", err, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(shutdown)
|
ln.Close()
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
// LookupCNAME does not return an error if host does not
|
||||||
// contain DNS "CNAME" records, as long as host resolves to
|
// contain DNS "CNAME" records, as long as host resolves to
|
||||||
// address records.
|
// 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) {
|
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.
|
// 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
|
// LookupCNAME does not return an error if host does not
|
||||||
// contain DNS "CNAME" records, as long as host resolves to
|
// contain DNS "CNAME" records, as long as host resolves to
|
||||||
// address records.
|
// 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,
|
// 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
|
// That is, it looks up _service._proto.name. To accommodate services
|
||||||
// publishing SRV records under non-standard names, if both service
|
// publishing SRV records under non-standard names, if both service
|
||||||
// and proto are empty strings, LookupSRV looks up name directly.
|
// 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) {
|
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,
|
// 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
|
// That is, it looks up _service._proto.name. To accommodate services
|
||||||
// publishing SRV records under non-standard names, if both service
|
// publishing SRV records under non-standard names, if both service
|
||||||
// and proto are empty strings, LookupSRV looks up name directly.
|
// 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.
|
// 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) {
|
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.
|
// 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) {
|
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.
|
// 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) {
|
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.
|
// 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) {
|
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.
|
// 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
|
// LookupAddr performs a reverse lookup for the given address, returning a list
|
||||||
// of names mapping to that address.
|
// 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
|
// When using the host C library resolver, at most one result will be
|
||||||
// returned. To bypass the host resolver, use a custom Resolver.
|
// returned. To bypass the host resolver, use a custom Resolver.
|
||||||
func LookupAddr(addr string) (names []string, err error) {
|
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
|
// LookupAddr performs a reverse lookup for the given address, returning a list
|
||||||
// of names mapping to that address.
|
// 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
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"runtime/trace"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -853,3 +854,44 @@ func TestNotifyContextStringer(t *testing.T) {
|
||||||
t.Errorf("c.String() = %q, want %q", got, want)
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -279,7 +279,8 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri
|
||||||
|
|
||||||
broken := false
|
broken := false
|
||||||
switch runtime.GOOS {
|
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
|
broken = true
|
||||||
case "openbsd":
|
case "openbsd":
|
||||||
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
|
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
|
||||||
|
|
|
@ -1287,6 +1287,9 @@ func mPark() {
|
||||||
g := getg()
|
g := getg()
|
||||||
for {
|
for {
|
||||||
notesleep(&g.m.park)
|
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)
|
noteclear(&g.m.park)
|
||||||
if !mDoFixup() {
|
if !mDoFixup() {
|
||||||
return
|
return
|
||||||
|
@ -1949,9 +1952,21 @@ var mFixupRace struct {
|
||||||
// mDoFixup runs any outstanding fixup function for the running m.
|
// mDoFixup runs any outstanding fixup function for the running m.
|
||||||
// Returns true if a fixup was outstanding and actually executed.
|
// 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
|
//go:nosplit
|
||||||
func mDoFixup() bool {
|
func mDoFixup() bool {
|
||||||
_g_ := getg()
|
_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)
|
lock(&_g_.m.mFixup.lock)
|
||||||
fn := _g_.m.mFixup.fn
|
fn := _g_.m.mFixup.fn
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
|
@ -1972,9 +1987,20 @@ func mDoFixup() bool {
|
||||||
fn(false)
|
fn(false)
|
||||||
}
|
}
|
||||||
unlock(&_g_.m.mFixup.lock)
|
unlock(&_g_.m.mFixup.lock)
|
||||||
|
msigrestore(sigmask)
|
||||||
return fn != nil
|
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
|
// templateThread is a thread in a known-good state that exists solely
|
||||||
// to start new threads in known-good states when the calling thread
|
// to start new threads in known-good states when the calling thread
|
||||||
// may not be in a good state.
|
// may not be in a good state.
|
||||||
|
|
|
@ -584,10 +584,13 @@ type m struct {
|
||||||
syscalltick uint32
|
syscalltick uint32
|
||||||
freelink *m // on sched.freem
|
freelink *m // on sched.freem
|
||||||
|
|
||||||
// mFixup is used to synchronize OS related m state (credentials etc)
|
// mFixup is used to synchronize OS related m state
|
||||||
// use mutex to access.
|
// (credentials etc) use mutex to access. To avoid deadlocks
|
||||||
|
// an atomic.Load() of used being zero in mDoFixupFn()
|
||||||
|
// guarantees fn is nil.
|
||||||
mFixup struct {
|
mFixup struct {
|
||||||
lock mutex
|
lock mutex
|
||||||
|
used uint32
|
||||||
fn func(bool) bool
|
fn func(bool) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ Send:
|
||||||
}
|
}
|
||||||
case sigFixup:
|
case sigFixup:
|
||||||
// nothing to do - we need to wait for sigIdle.
|
// nothing to do - we need to wait for sigIdle.
|
||||||
osyield()
|
mDoFixupAndOSYield()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
// If we're at the end of the known zone transitions,
|
||||||
// try the extend string.
|
// try the extend string.
|
||||||
if lo == len(tx)-1 && l.extend != "" {
|
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
|
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.
|
// 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
|
// The return values are as for lookup, plus ok which reports whether the
|
||||||
// parse succeeded.
|
// 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 (
|
var (
|
||||||
stdName, dstName string
|
stdName, dstName string
|
||||||
stdOffset, dstOffset int
|
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)
|
stdOffset, s, ok = tzsetOffset(s)
|
||||||
}
|
}
|
||||||
if !ok {
|
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,
|
// 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] == ',' {
|
if len(s) == 0 || s[0] == ',' {
|
||||||
// No daylight savings time.
|
// No daylight savings time.
|
||||||
return stdName, stdOffset, initEnd, omega, true
|
return stdName, stdOffset, initEnd, omega, false, true
|
||||||
}
|
}
|
||||||
|
|
||||||
dstName, s, ok = tzsetName(s)
|
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 {
|
if !ok {
|
||||||
return "", 0, 0, 0, false
|
return "", 0, 0, 0, false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s) == 0 {
|
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.
|
// The TZ definition does not mention ';' here but tzcode accepts it.
|
||||||
if s[0] != ',' && s[0] != ';' {
|
if s[0] != ',' && s[0] != ';' {
|
||||||
return "", 0, 0, 0, false
|
return "", 0, 0, 0, false, false
|
||||||
}
|
}
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
|
|
||||||
var startRule, endRule rule
|
var startRule, endRule rule
|
||||||
startRule, s, ok = tzsetRule(s)
|
startRule, s, ok = tzsetRule(s)
|
||||||
if !ok || len(s) == 0 || s[0] != ',' {
|
if !ok || len(s) == 0 || s[0] != ',' {
|
||||||
return "", 0, 0, 0, false
|
return "", 0, 0, 0, false, false
|
||||||
}
|
}
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
endRule, s, ok = tzsetRule(s)
|
endRule, s, ok = tzsetRule(s)
|
||||||
if !ok || len(s) > 0 {
|
if !ok || len(s) > 0 {
|
||||||
return "", 0, 0, 0, false
|
return "", 0, 0, 0, false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
year, _, _, yday := absDate(uint64(sec+unixToInternal+internalToAbsolute), 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))
|
startSec := int64(tzruleTime(year, startRule, stdOffset))
|
||||||
endSec := int64(tzruleTime(year, endRule, dstOffset))
|
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 {
|
if endSec < startSec {
|
||||||
startSec, endSec = endSec, startSec
|
startSec, endSec = endSec, startSec
|
||||||
stdName, dstName = dstName, stdName
|
stdName, dstName = dstName, stdName
|
||||||
stdOffset, dstOffset = dstOffset, stdOffset
|
stdOffset, dstOffset = dstOffset, stdOffset
|
||||||
|
stdIsDST, dstIsDST = dstIsDST, stdIsDST
|
||||||
}
|
}
|
||||||
|
|
||||||
// The start and end values that we return are accurate
|
// 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
|
// just the start and end of the year. That suffices for
|
||||||
// the only caller that cares, which is Date.
|
// the only caller that cares, which is Date.
|
||||||
if ysec < startSec {
|
if ysec < startSec {
|
||||||
return stdName, stdOffset, abs, startSec + abs, true
|
return stdName, stdOffset, abs, startSec + abs, stdIsDST, true
|
||||||
} else if ysec >= endSec {
|
} else if ysec >= endSec {
|
||||||
return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, true
|
return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, stdIsDST, true
|
||||||
} else {
|
} else {
|
||||||
return dstName, dstOffset, startSec + abs, endSec + abs, true
|
return dstName, dstOffset, startSec + abs, endSec + abs, dstIsDST, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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).
|
// This also avoids a panic later when we add and then use a fake transition (golang.org/issue/29437).
|
||||||
return nil, badData
|
return nil, badData
|
||||||
}
|
}
|
||||||
zone := make([]zone, nzone)
|
zones := make([]zone, nzone)
|
||||||
for i := range zone {
|
for i := range zones {
|
||||||
var ok bool
|
var ok bool
|
||||||
var n uint32
|
var n uint32
|
||||||
if n, ok = zonedata.big4(); !ok {
|
if n, ok = zonedata.big4(); !ok {
|
||||||
|
@ -259,22 +259,22 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
|
||||||
if uint32(int(n)) != n {
|
if uint32(int(n)) != n {
|
||||||
return nil, badData
|
return nil, badData
|
||||||
}
|
}
|
||||||
zone[i].offset = int(int32(n))
|
zones[i].offset = int(int32(n))
|
||||||
var b byte
|
var b byte
|
||||||
if b, ok = zonedata.byte(); !ok {
|
if b, ok = zonedata.byte(); !ok {
|
||||||
return nil, badData
|
return nil, badData
|
||||||
}
|
}
|
||||||
zone[i].isDST = b != 0
|
zones[i].isDST = b != 0
|
||||||
if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) {
|
if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) {
|
||||||
return nil, badData
|
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-") {
|
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,
|
// 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.
|
// GMT+1 will return GMT-1 instead of GMT+1 or -01.
|
||||||
if name != "Etc/GMT+0" {
|
if name != "Etc/GMT+0" {
|
||||||
// GMT+0 is OK
|
// 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
|
tx[i].when = n
|
||||||
if int(txzones[i]) >= len(zone) {
|
if int(txzones[i]) >= len(zones) {
|
||||||
return nil, badData
|
return nil, badData
|
||||||
}
|
}
|
||||||
tx[i].index = txzones[i]
|
tx[i].index = txzones[i]
|
||||||
|
@ -316,7 +316,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Committed to succeed.
|
// 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,
|
// Fill in the cache with information about right now,
|
||||||
// since that will be the most common lookup.
|
// 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) {
|
if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
|
||||||
l.cacheStart = tx[i].when
|
l.cacheStart = tx[i].when
|
||||||
l.cacheEnd = omega
|
l.cacheEnd = omega
|
||||||
zoneIdx := tx[i].index
|
l.cacheZone = &l.zone[tx[i].index]
|
||||||
if i+1 < len(tx) {
|
if i+1 < len(tx) {
|
||||||
l.cacheEnd = tx[i+1].when
|
l.cacheEnd = tx[i+1].when
|
||||||
} else if l.extend != "" {
|
} else if l.extend != "" {
|
||||||
// If we're at the end of the known zone transitions,
|
// If we're at the end of the known zone transitions,
|
||||||
// try the extend string.
|
// 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.cacheStart = estart
|
||||||
l.cacheEnd = eend
|
l.cacheEnd = eend
|
||||||
// Find the zone that is returned by tzset,
|
// Find the zone that is returned by tzset to avoid allocation if possible.
|
||||||
// the last transition is not always the correct zone.
|
if zoneIdx := findZone(l.zone, name, offset, isDST); zoneIdx != -1 {
|
||||||
for i, z := range l.zone {
|
l.cacheZone = &l.zone[zoneIdx]
|
||||||
if z.name == name {
|
} else {
|
||||||
zoneIdx = uint8(i)
|
l.cacheZone = &zone{
|
||||||
break
|
name: name,
|
||||||
|
offset: offset,
|
||||||
|
isDST: isDST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.cacheZone = &l.zone[zoneIdx]
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,6 +353,15 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
|
||||||
return l, nil
|
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
|
// loadTzinfoFromDirOrZip returns the contents of the file with the given name
|
||||||
// in dir. dir can either be an uncompressed zip file, or a directory.
|
// in dir. dir can either be an uncompressed zip file, or a directory.
|
||||||
func loadTzinfoFromDirOrZip(dir, name string) ([]byte, error) {
|
func loadTzinfoFromDirOrZip(dir, name string) ([]byte, error) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519
|
||||||
golang.org/x/crypto/hkdf
|
golang.org/x/crypto/hkdf
|
||||||
golang.org/x/crypto/internal/subtle
|
golang.org/x/crypto/internal/subtle
|
||||||
golang.org/x/crypto/poly1305
|
golang.org/x/crypto/poly1305
|
||||||
# golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
|
# golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b
|
||||||
## explicit
|
## explicit
|
||||||
golang.org/x/net/dns/dnsmessage
|
golang.org/x/net/dns/dnsmessage
|
||||||
golang.org/x/net/http/httpguts
|
golang.org/x/net/http/httpguts
|
||||||
|
|
Loading…
Reference in New Issue